grpc 1.55.3 → 1.56.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +100 -70
- data/include/grpc/event_engine/event_engine.h +4 -3
- data/include/grpc/grpc_audit_logging.h +96 -0
- data/include/grpc/module.modulemap +2 -0
- data/include/grpc/support/json.h +218 -0
- data/src/core/ext/filters/backend_metrics/backend_metric_filter.cc +5 -0
- data/src/core/ext/filters/client_channel/backend_metric.cc +2 -0
- data/src/core/ext/filters/client_channel/channel_connectivity.cc +4 -4
- data/src/core/ext/filters/client_channel/client_channel.cc +82 -98
- data/src/core/ext/filters/client_channel/client_channel.h +4 -0
- data/src/core/ext/filters/client_channel/client_channel_channelz.cc +19 -18
- data/src/core/ext/filters/client_channel/client_channel_internal.h +16 -21
- data/src/core/ext/filters/client_channel/config_selector.h +9 -24
- data/src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h +3 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +5 -4
- data/src/core/ext/filters/client_channel/lb_policy/health_check_client.cc +455 -0
- data/src/core/ext/filters/client_channel/lb_policy/health_check_client.h +54 -0
- data/src/core/ext/filters/client_channel/lb_policy/health_check_client_internal.h +186 -0
- data/src/core/ext/filters/client_channel/lb_policy/oob_backend_metric.cc +2 -7
- data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc +52 -20
- data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.h +23 -2
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +19 -6
- data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +1 -9
- data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +16 -7
- data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +18 -1
- data/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +12 -9
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +6 -4
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +36 -13
- data/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/static_stride_scheduler.cc +76 -6
- data/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc +32 -39
- data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +4 -10
- data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +52 -47
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +1 -9
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +14 -16
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +40 -43
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc +7 -12
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_wrr_locality.cc +12 -19
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +35 -33
- data/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc +29 -4
- data/src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc +1 -1
- data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +28 -27
- data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +163 -46
- data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h +16 -1
- data/src/core/ext/filters/client_channel/retry_service_config.cc +1 -0
- data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +10 -40
- data/src/core/ext/filters/client_channel/subchannel.cc +10 -196
- data/src/core/ext/filters/client_channel/subchannel.h +3 -43
- data/src/core/ext/filters/http/message_compress/compression_filter.cc +5 -5
- data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +100 -6
- data/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc +6 -8
- data/src/core/ext/filters/stateful_session/stateful_session_filter.cc +3 -3
- data/src/core/ext/filters/stateful_session/stateful_session_filter.h +16 -1
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +46 -95
- data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +543 -567
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +9 -150
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +32 -46
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +5 -18
- data/src/core/ext/transport/chttp2/transport/internal.h +1 -15
- data/src/core/ext/transport/chttp2/transport/parsing.cc +12 -12
- data/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c +11 -2
- data/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h +15 -0
- data/src/core/ext/xds/certificate_provider_store.cc +4 -9
- data/src/core/ext/xds/certificate_provider_store.h +1 -1
- data/src/core/ext/xds/file_watcher_certificate_provider_factory.cc +30 -42
- data/src/core/ext/xds/file_watcher_certificate_provider_factory.h +14 -9
- data/src/core/ext/xds/xds_api.cc +9 -6
- data/src/core/ext/xds/xds_api.h +3 -2
- data/src/core/ext/xds/xds_audit_logger_registry.cc +122 -0
- data/src/core/ext/xds/xds_audit_logger_registry.h +68 -0
- data/src/core/ext/xds/xds_bootstrap_grpc.cc +21 -9
- data/src/core/ext/xds/xds_bootstrap_grpc.h +5 -0
- data/src/core/ext/xds/xds_client.cc +5 -4
- data/src/core/ext/xds/xds_client_stats.h +1 -1
- data/src/core/ext/xds/xds_cluster.cc +20 -19
- data/src/core/ext/xds/xds_cluster_specifier_plugin.cc +11 -8
- data/src/core/ext/xds/xds_common_types.cc +3 -1
- data/src/core/ext/xds/xds_http_fault_filter.cc +16 -13
- data/src/core/ext/xds/xds_http_fault_filter.h +2 -1
- data/src/core/ext/xds/xds_http_filters.h +4 -2
- data/src/core/ext/xds/xds_http_rbac_filter.cc +154 -67
- data/src/core/ext/xds/xds_http_rbac_filter.h +2 -1
- data/src/core/ext/xds/xds_http_stateful_session_filter.cc +15 -11
- data/src/core/ext/xds/xds_http_stateful_session_filter.h +2 -1
- data/src/core/ext/xds/xds_lb_policy_registry.cc +22 -16
- data/src/core/ext/xds/xds_listener.cc +1 -0
- data/src/core/ext/xds/xds_route_config.cc +40 -3
- data/src/core/ext/xds/xds_routing.cc +2 -2
- data/src/core/ext/xds/xds_transport_grpc.cc +3 -1
- data/src/core/lib/avl/avl.h +5 -0
- data/src/core/lib/backoff/random_early_detection.h +0 -5
- data/src/core/lib/channel/channel_args.cc +80 -22
- data/src/core/lib/channel/channel_args.h +34 -1
- data/src/core/lib/channel/channel_trace.cc +16 -12
- data/src/core/lib/channel/channelz.cc +159 -132
- data/src/core/lib/channel/channelz.h +42 -35
- data/src/core/lib/channel/channelz_registry.cc +23 -20
- data/src/core/lib/channel/connected_channel.cc +17 -6
- data/src/core/lib/channel/promise_based_filter.cc +0 -4
- data/src/core/lib/channel/promise_based_filter.h +2 -0
- data/src/core/lib/compression/compression_internal.cc +2 -5
- data/src/core/lib/config/config_vars.cc +20 -18
- data/src/core/lib/config/config_vars.h +4 -4
- data/src/core/lib/config/load_config.cc +13 -0
- data/src/core/lib/config/load_config.h +6 -0
- data/src/core/lib/debug/event_log.h +1 -1
- data/src/core/lib/debug/stats_data.h +1 -1
- data/src/core/lib/debug/trace.cc +24 -55
- data/src/core/lib/debug/trace.h +3 -1
- data/src/core/lib/event_engine/cf_engine/cf_engine.cc +211 -0
- data/src/core/lib/event_engine/cf_engine/cf_engine.h +86 -0
- data/src/core/lib/event_engine/cf_engine/cfstream_endpoint.cc +354 -0
- data/src/core/lib/event_engine/cf_engine/cfstream_endpoint.h +146 -0
- data/src/core/lib/event_engine/cf_engine/cftype_unique_ref.h +79 -0
- data/src/core/lib/event_engine/default_event_engine.cc +13 -1
- data/src/core/lib/event_engine/default_event_engine_factory.cc +14 -2
- data/src/core/lib/event_engine/poller.h +2 -2
- data/src/core/lib/event_engine/posix.h +4 -0
- data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc +1 -1
- data/src/core/lib/event_engine/posix_engine/lockfree_event.cc +7 -18
- data/src/core/lib/event_engine/posix_engine/posix_endpoint.h +9 -0
- data/src/core/lib/event_engine/posix_engine/posix_engine.cc +3 -2
- data/src/core/lib/event_engine/posix_engine/posix_engine.h +1 -2
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +4 -33
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.h +7 -11
- data/src/core/lib/event_engine/posix_engine/timer_manager.h +1 -1
- data/src/core/lib/event_engine/shim.cc +7 -1
- data/src/core/lib/event_engine/{thread_pool.cc → thread_pool/original_thread_pool.cc} +28 -25
- data/src/core/lib/event_engine/{thread_pool.h → thread_pool/original_thread_pool.h} +11 -15
- data/src/core/lib/event_engine/thread_pool/thread_pool.h +50 -0
- data/src/core/lib/event_engine/{executor/executor.h → thread_pool/thread_pool_factory.cc} +17 -15
- data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc +489 -0
- data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.h +249 -0
- data/src/core/lib/event_engine/thready_event_engine/thready_event_engine.cc +166 -0
- data/src/core/lib/event_engine/thready_event_engine/thready_event_engine.h +108 -0
- data/src/core/lib/event_engine/windows/iocp.cc +4 -3
- data/src/core/lib/event_engine/windows/iocp.h +3 -3
- data/src/core/lib/event_engine/windows/win_socket.cc +6 -6
- data/src/core/lib/event_engine/windows/win_socket.h +4 -4
- data/src/core/lib/event_engine/windows/windows_endpoint.cc +11 -10
- data/src/core/lib/event_engine/windows/windows_endpoint.h +3 -2
- data/src/core/lib/event_engine/windows/windows_engine.cc +19 -17
- data/src/core/lib/event_engine/windows/windows_engine.h +6 -6
- data/src/core/lib/event_engine/windows/windows_listener.cc +3 -3
- data/src/core/lib/event_engine/windows/windows_listener.h +3 -2
- data/src/core/lib/event_engine/work_queue/basic_work_queue.cc +63 -0
- data/src/core/lib/event_engine/work_queue/basic_work_queue.h +71 -0
- data/src/core/lib/event_engine/work_queue/work_queue.h +62 -0
- data/src/core/lib/experiments/config.cc +38 -7
- data/src/core/lib/experiments/config.h +16 -0
- data/src/core/lib/experiments/experiments.cc +67 -20
- data/src/core/lib/experiments/experiments.h +27 -21
- data/src/core/lib/gpr/log_internal.h +55 -0
- data/src/core/lib/gprpp/crash.cc +10 -0
- data/src/core/lib/gprpp/crash.h +3 -0
- data/src/core/lib/gprpp/per_cpu.cc +33 -0
- data/src/core/lib/gprpp/per_cpu.h +29 -6
- data/src/core/lib/gprpp/time.cc +1 -0
- data/src/core/lib/iomgr/cfstream_handle.cc +1 -1
- data/src/core/lib/iomgr/endpoint_cfstream.cc +10 -8
- data/src/core/lib/iomgr/ev_apple.cc +12 -12
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +10 -3
- data/src/core/lib/iomgr/event_engine_shims/endpoint.cc +15 -1
- data/src/core/lib/iomgr/iocp_windows.cc +24 -3
- data/src/core/lib/iomgr/iocp_windows.h +11 -0
- data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +1 -1
- data/src/core/lib/iomgr/socket_utils_common_posix.cc +4 -2
- data/src/core/lib/iomgr/socket_windows.cc +61 -7
- data/src/core/lib/iomgr/socket_windows.h +9 -2
- data/src/core/lib/iomgr/tcp_client_cfstream.cc +14 -3
- data/src/core/lib/iomgr/tcp_server_posix.cc +156 -140
- data/src/core/lib/iomgr/tcp_server_utils_posix.h +1 -13
- data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +0 -21
- data/src/core/lib/iomgr/tcp_server_windows.cc +1 -1
- data/src/core/lib/json/json.h +2 -166
- data/src/core/lib/json/json_object_loader.cc +8 -9
- data/src/core/lib/json/json_object_loader.h +25 -18
- data/src/core/lib/json/json_reader.cc +13 -6
- data/src/core/lib/json/json_util.cc +6 -11
- data/src/core/lib/json/json_writer.cc +7 -8
- data/src/core/lib/load_balancing/lb_policy.h +13 -0
- data/src/core/lib/load_balancing/lb_policy_registry.cc +2 -1
- data/src/core/lib/matchers/matchers.cc +3 -4
- data/src/core/lib/matchers/matchers.h +2 -1
- data/src/core/lib/promise/activity.cc +5 -0
- data/src/core/lib/promise/activity.h +10 -0
- data/src/core/lib/promise/detail/promise_factory.h +1 -1
- data/src/core/lib/promise/party.cc +31 -13
- data/src/core/lib/promise/party.h +11 -2
- data/src/core/lib/promise/pipe.h +9 -2
- data/src/core/lib/promise/prioritized_race.h +95 -0
- data/src/core/lib/promise/sleep.cc +2 -1
- data/src/core/lib/resolver/server_address.cc +0 -8
- data/src/core/lib/resolver/server_address.h +0 -6
- data/src/core/lib/resource_quota/memory_quota.cc +7 -7
- data/src/core/lib/resource_quota/memory_quota.h +1 -2
- data/src/core/lib/security/authorization/audit_logging.cc +98 -0
- data/src/core/lib/security/authorization/audit_logging.h +73 -0
- data/src/core/lib/security/authorization/grpc_authorization_engine.cc +47 -2
- data/src/core/lib/security/authorization/grpc_authorization_engine.h +18 -1
- data/src/core/lib/security/authorization/rbac_policy.cc +36 -4
- data/src/core/lib/security/authorization/rbac_policy.h +19 -2
- data/src/core/lib/security/authorization/stdout_logger.cc +75 -0
- data/src/core/lib/security/authorization/stdout_logger.h +61 -0
- data/src/core/lib/security/certificate_provider/certificate_provider_factory.h +8 -4
- data/src/core/lib/security/certificate_provider/certificate_provider_registry.cc +8 -18
- data/src/core/lib/security/certificate_provider/certificate_provider_registry.h +14 -8
- data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +19 -12
- data/src/core/lib/security/credentials/external/external_account_credentials.cc +4 -2
- data/src/core/lib/security/credentials/external/file_external_account_credentials.cc +1 -0
- data/src/core/lib/security/credentials/external/url_external_account_credentials.cc +1 -0
- data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +1 -0
- data/src/core/lib/security/credentials/jwt/json_token.cc +15 -14
- data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +4 -2
- data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +1 -0
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -0
- data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +1 -5
- data/src/core/lib/security/util/json_util.cc +1 -0
- data/src/core/lib/service_config/service_config_call_data.h +49 -20
- data/src/core/lib/service_config/service_config_impl.cc +2 -1
- data/src/core/lib/surface/call.cc +38 -23
- data/src/core/lib/surface/completion_queue.cc +6 -2
- data/src/core/lib/surface/validate_metadata.cc +22 -37
- data/src/core/lib/surface/validate_metadata.h +3 -13
- data/src/core/lib/surface/version.cc +2 -2
- data/src/core/lib/transport/batch_builder.cc +15 -12
- data/src/core/lib/transport/batch_builder.h +39 -35
- data/src/core/plugin_registry/grpc_plugin_registry.cc +0 -2
- data/src/core/plugin_registry/grpc_plugin_registry_extra.cc +2 -0
- data/src/ruby/ext/grpc/extconf.rb +8 -9
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/asn1/a_mbstr.c +9 -8
- data/third_party/boringssl-with-bazel/src/crypto/asn1/a_strnid.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/asn1/internal.h +3 -3
- data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_dec.c +10 -6
- data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_enc.c +7 -4
- data/third_party/boringssl-with-bazel/src/crypto/bio/bio.c +6 -4
- data/third_party/boringssl-with-bazel/src/crypto/bio/fd.c +2 -1
- data/third_party/boringssl-with-bazel/src/crypto/bio/file.c +5 -9
- data/third_party/boringssl-with-bazel/src/crypto/bio/pair.c +4 -2
- data/third_party/boringssl-with-bazel/src/crypto/blake2/blake2.c +31 -22
- data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_tls.c +29 -26
- data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/internal.h +8 -0
- data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/tls_cbc.c +189 -13
- data/third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_openbsd.c +62 -0
- data/third_party/boringssl-with-bazel/src/crypto/cpu_arm_openbsd.c +31 -0
- data/third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c +6 -4
- data/third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519_tables.h +795 -795
- data/third_party/boringssl-with-bazel/src/crypto/curve25519/internal.h +1 -5
- data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa.c +4 -0
- data/third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c +18 -6
- data/third_party/boringssl-with-bazel/src/crypto/ec_extra/internal.h +15 -7
- data/third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/evp/p_rsa.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c +1 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/dh/dh.c +3 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec.c +24 -24
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_key.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_montgomery.c +7 -7
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/internal.h +74 -74
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/oct.c +1 -2
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p224-64.c +11 -11
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-nistz.c +12 -12
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256.c +14 -15
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256_table.h +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple.c +10 -10
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple_mul.c +23 -23
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/wnaf.c +13 -13
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdh/ecdh.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/ecdsa.c +2 -2
- data/third_party/boringssl-with-bazel/src/crypto/{hkdf → fipsmodule/hkdf}/hkdf.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/cbc.c +2 -10
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/ctr.c +1 -4
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/gcm.c +115 -133
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/gcm_nohw.c +12 -14
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/internal.h +57 -47
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/ofb.c +1 -8
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/polyval.c +27 -28
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c +11 -23
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/internal.h +21 -16
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/padding.c +5 -288
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa.c +143 -83
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +95 -183
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/self_check/self_check.c +71 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/internal.h +8 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/kdf.c +33 -0
- data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +162 -6
- data/third_party/boringssl-with-bazel/src/crypto/internal.h +18 -0
- data/third_party/boringssl-with-bazel/src/crypto/kyber/kyber.c +18 -11
- data/third_party/boringssl-with-bazel/src/crypto/obj/obj_dat.h +6 -13
- data/third_party/boringssl-with-bazel/src/crypto/pem/pem_lib.c +18 -14
- data/third_party/boringssl-with-bazel/src/crypto/{refcount_lock.c → refcount_no_threads.c} +3 -13
- data/third_party/boringssl-with-bazel/src/crypto/refcount_win.c +89 -0
- data/third_party/boringssl-with-bazel/src/crypto/rsa_extra/internal.h +77 -0
- data/third_party/boringssl-with-bazel/src/crypto/rsa_extra/rsa_crypt.c +568 -0
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h +62 -0
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c +218 -44
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c +35 -0
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/voprf.c +588 -39
- data/third_party/boringssl-with-bazel/src/crypto/x509/a_sign.c +27 -18
- data/third_party/boringssl-with-bazel/src/crypto/x509/asn1_gen.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/x509/name_print.c +17 -39
- data/third_party/boringssl-with-bazel/src/crypto/x509/t_x509.c +39 -48
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_att.c +0 -140
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c +72 -23
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509name.c +11 -14
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509spki.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509a.c +2 -2
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/internal.h +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_conf.c +33 -46
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_cpols.c +1 -0
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_info.c +3 -5
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_lib.c +14 -46
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_prn.c +14 -26
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_skey.c +17 -10
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_utl.c +1 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/aead.h +5 -7
- data/third_party/boringssl-with-bazel/src/include/openssl/asn1.h +6 -4
- data/third_party/boringssl-with-bazel/src/include/openssl/base.h +32 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/bio.h +0 -4
- data/third_party/boringssl-with-bazel/src/include/openssl/blake2.h +1 -4
- data/third_party/boringssl-with-bazel/src/include/openssl/evp.h +3 -3
- data/third_party/boringssl-with-bazel/src/include/openssl/hpke.h +28 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/nid.h +2 -11
- data/third_party/boringssl-with-bazel/src/include/openssl/pem.h +0 -3
- data/third_party/boringssl-with-bazel/src/include/openssl/rsa.h +91 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/span.h +5 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +149 -20
- data/third_party/boringssl-with-bazel/src/include/openssl/thread.h +4 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/tls1.h +4 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/trust_token.h +8 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +774 -615
- data/third_party/boringssl-with-bazel/src/include/openssl/x509v3.h +42 -10
- data/third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc +11 -6
- data/third_party/boringssl-with-bazel/src/ssl/extensions.cc +2 -4
- data/third_party/boringssl-with-bazel/src/ssl/handshake_client.cc +24 -16
- data/third_party/boringssl-with-bazel/src/ssl/internal.h +65 -18
- data/third_party/boringssl-with-bazel/src/ssl/s3_both.cc +37 -18
- data/third_party/boringssl-with-bazel/src/ssl/ssl_cipher.cc +187 -193
- data/third_party/boringssl-with-bazel/src/ssl/ssl_key_share.cc +13 -129
- data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +85 -10
- data/third_party/boringssl-with-bazel/src/ssl/ssl_privkey.cc +17 -4
- data/third_party/boringssl-with-bazel/src/ssl/ssl_versions.cc +27 -19
- data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +1 -1
- data/third_party/boringssl-with-bazel/src/ssl/tls13_enc.cc +5 -21
- data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +5 -2
- data/third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_64_msvc.h +1281 -0
- data/third_party/boringssl-with-bazel/src/third_party/fiat/p256_64_msvc.h +2002 -0
- data/third_party/cares/cares/include/ares.h +23 -1
- data/third_party/cares/cares/{src/lib → include}/ares_nameser.h +9 -7
- data/third_party/cares/cares/include/ares_rules.h +2 -2
- data/third_party/cares/cares/include/ares_version.h +3 -3
- data/third_party/cares/cares/src/lib/ares__addrinfo2hostent.c +266 -0
- data/third_party/cares/cares/src/lib/ares__addrinfo_localhost.c +240 -0
- data/third_party/cares/cares/src/lib/ares__parse_into_addrinfo.c +49 -80
- data/third_party/cares/cares/src/lib/ares__readaddrinfo.c +37 -43
- data/third_party/cares/cares/src/lib/ares__sortaddrinfo.c +12 -4
- data/third_party/cares/cares/src/lib/ares_data.c +16 -0
- data/third_party/cares/cares/src/lib/ares_data.h +7 -0
- data/third_party/cares/cares/src/lib/ares_destroy.c +8 -0
- data/third_party/cares/cares/src/lib/ares_expand_name.c +17 -6
- data/third_party/cares/cares/src/lib/ares_freeaddrinfo.c +1 -0
- data/third_party/cares/cares/src/lib/ares_getaddrinfo.c +156 -78
- data/third_party/cares/cares/src/lib/ares_gethostbyname.c +130 -326
- data/third_party/cares/cares/src/lib/ares_init.c +97 -485
- data/third_party/cares/cares/src/lib/ares_library_init.c +2 -89
- data/third_party/cares/cares/src/lib/ares_parse_a_reply.c +23 -142
- data/third_party/cares/cares/src/lib/ares_parse_aaaa_reply.c +22 -142
- data/third_party/cares/cares/src/lib/ares_parse_uri_reply.c +184 -0
- data/third_party/cares/cares/src/lib/ares_private.h +30 -16
- data/third_party/cares/cares/src/lib/ares_process.c +55 -16
- data/third_party/cares/cares/src/lib/ares_query.c +1 -35
- data/third_party/cares/cares/src/lib/ares_rand.c +279 -0
- data/third_party/cares/cares/src/lib/ares_send.c +5 -7
- data/third_party/cares/cares/src/lib/ares_strdup.c +12 -19
- data/third_party/cares/cares/src/lib/ares_strsplit.c +44 -128
- data/third_party/cares/cares/src/lib/ares_strsplit.h +9 -10
- data/third_party/cares/cares/src/lib/inet_net_pton.c +78 -116
- data/third_party/cares/cares/src/tools/ares_getopt.h +53 -0
- metadata +50 -16
- data/src/core/ext/filters/client_channel/health/health_check_client.cc +0 -175
- data/src/core/ext/filters/client_channel/health/health_check_client.h +0 -43
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +0 -176
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +0 -325
- data/third_party/cares/cares/src/lib/ares_library_init.h +0 -43
@@ -24,6 +24,7 @@
|
|
24
24
|
#include <stdlib.h>
|
25
25
|
|
26
26
|
#include <algorithm>
|
27
|
+
#include <initializer_list>
|
27
28
|
#include <string>
|
28
29
|
#include <utility>
|
29
30
|
|
@@ -31,22 +32,21 @@
|
|
31
32
|
#include "absl/status/status.h"
|
32
33
|
#include "absl/strings/match.h"
|
33
34
|
#include "absl/strings/str_cat.h"
|
35
|
+
#include "absl/strings/str_format.h"
|
34
36
|
#include "absl/strings/string_view.h"
|
35
37
|
#include "absl/types/optional.h"
|
36
38
|
#include "absl/types/span.h"
|
37
39
|
#include "absl/types/variant.h"
|
38
40
|
|
39
|
-
#include <grpc/slice.h>
|
40
41
|
#include <grpc/support/log.h>
|
41
42
|
|
42
43
|
#include "src/core/ext/transport/chttp2/transport/decode_huff.h"
|
43
44
|
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
|
44
|
-
#include "src/core/ext/transport/chttp2/transport/hpack_parse_result.h"
|
45
|
-
#include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h"
|
46
45
|
#include "src/core/lib/debug/stats.h"
|
47
46
|
#include "src/core/lib/debug/stats_data.h"
|
48
47
|
#include "src/core/lib/debug/trace.h"
|
49
|
-
#include "src/core/lib/gprpp/
|
48
|
+
#include "src/core/lib/gprpp/crash.h"
|
49
|
+
#include "src/core/lib/gprpp/status_helper.h"
|
50
50
|
#include "src/core/lib/slice/slice.h"
|
51
51
|
#include "src/core/lib/slice/slice_refcount.h"
|
52
52
|
#include "src/core/lib/surface/validate_metadata.h"
|
@@ -82,6 +82,39 @@ struct Base64InverseTable {
|
|
82
82
|
|
83
83
|
constexpr Base64InverseTable kBase64InverseTable;
|
84
84
|
|
85
|
+
absl::Status EnsureStreamError(absl::Status error) {
|
86
|
+
if (error.ok()) return error;
|
87
|
+
return grpc_error_set_int(std::move(error), StatusIntProperty::kStreamId, 0);
|
88
|
+
}
|
89
|
+
|
90
|
+
bool IsStreamError(const absl::Status& status) {
|
91
|
+
intptr_t stream_id;
|
92
|
+
return grpc_error_get_int(status, StatusIntProperty::kStreamId, &stream_id);
|
93
|
+
}
|
94
|
+
|
95
|
+
class MetadataSizeLimitExceededEncoder {
|
96
|
+
public:
|
97
|
+
explicit MetadataSizeLimitExceededEncoder(std::string& summary)
|
98
|
+
: summary_(summary) {}
|
99
|
+
|
100
|
+
void Encode(const Slice& key, const Slice& value) {
|
101
|
+
AddToSummary(key.as_string_view(), value.size());
|
102
|
+
}
|
103
|
+
|
104
|
+
template <typename Key, typename Value>
|
105
|
+
void Encode(Key, const Value& value) {
|
106
|
+
AddToSummary(Key::key(), EncodedSizeOfKey(Key(), value));
|
107
|
+
}
|
108
|
+
|
109
|
+
private:
|
110
|
+
void AddToSummary(absl::string_view key,
|
111
|
+
size_t value_length) GPR_ATTRIBUTE_NOINLINE {
|
112
|
+
absl::StrAppend(&summary_, " ", key, ":",
|
113
|
+
hpack_constants::SizeForEntry(key.size(), value_length),
|
114
|
+
"B");
|
115
|
+
}
|
116
|
+
std::string& summary_;
|
117
|
+
};
|
85
118
|
} // namespace
|
86
119
|
|
87
120
|
// Input tracks the current byte through the input data and provides it
|
@@ -89,12 +122,11 @@ constexpr Base64InverseTable kBase64InverseTable;
|
|
89
122
|
class HPackParser::Input {
|
90
123
|
public:
|
91
124
|
Input(grpc_slice_refcount* current_slice_refcount, const uint8_t* begin,
|
92
|
-
const uint8_t* end
|
125
|
+
const uint8_t* end)
|
93
126
|
: current_slice_refcount_(current_slice_refcount),
|
94
127
|
begin_(begin),
|
95
128
|
end_(end),
|
96
|
-
frontier_(begin)
|
97
|
-
error_(error) {}
|
129
|
+
frontier_(begin) {}
|
98
130
|
|
99
131
|
// If input is backed by a slice, retrieve its refcount. If not, return
|
100
132
|
// nullptr.
|
@@ -124,7 +156,7 @@ class HPackParser::Input {
|
|
124
156
|
// of stream
|
125
157
|
absl::optional<uint8_t> Next() {
|
126
158
|
if (end_of_stream()) {
|
127
|
-
UnexpectedEOF(
|
159
|
+
UnexpectedEOF();
|
128
160
|
return absl::optional<uint8_t>();
|
129
161
|
}
|
130
162
|
return *begin_++;
|
@@ -170,16 +202,9 @@ class HPackParser::Input {
|
|
170
202
|
|
171
203
|
// Spec weirdness: we can add an infinite stream of 0x80 at the end of a
|
172
204
|
// varint and still end up with a correctly encoded varint.
|
173
|
-
// We allow up to 16 just for kicks, but any more and we'll assume the
|
174
|
-
// sender is being malicious.
|
175
|
-
int num_redundant_0x80 = 0;
|
176
205
|
do {
|
177
206
|
cur = Next();
|
178
207
|
if (!cur.has_value()) return {};
|
179
|
-
++num_redundant_0x80;
|
180
|
-
if (num_redundant_0x80 == 16) {
|
181
|
-
return ParseVarintMaliciousEncoding();
|
182
|
-
}
|
183
208
|
} while (*cur == 0x80);
|
184
209
|
|
185
210
|
// BUT... the last byte needs to be 0x00 or we'll overflow dramatically!
|
@@ -187,6 +212,14 @@ class HPackParser::Input {
|
|
187
212
|
return ParseVarintOutOfRange(value, *cur);
|
188
213
|
}
|
189
214
|
|
215
|
+
// Prefix for a string
|
216
|
+
struct StringPrefix {
|
217
|
+
// Number of bytes in input for string
|
218
|
+
uint32_t length;
|
219
|
+
// Is it huffman compressed
|
220
|
+
bool huff;
|
221
|
+
};
|
222
|
+
|
190
223
|
// Parse a string prefix
|
191
224
|
absl::optional<StringPrefix> ParseStringPrefix() {
|
192
225
|
auto cur = Next();
|
@@ -210,13 +243,17 @@ class HPackParser::Input {
|
|
210
243
|
return StringPrefix{strlen, huff};
|
211
244
|
}
|
212
245
|
|
213
|
-
// Check if we saw an EOF
|
246
|
+
// Check if we saw an EOF.. must be verified before looking at TakeError
|
214
247
|
bool eof_error() const {
|
215
|
-
return
|
248
|
+
return eof_error_ || (!error_.ok() && !IsStreamError(error_));
|
216
249
|
}
|
217
250
|
|
218
|
-
//
|
219
|
-
|
251
|
+
// Extract the parse error, leaving the current error as NONE.
|
252
|
+
grpc_error_handle TakeError() {
|
253
|
+
grpc_error_handle out = error_;
|
254
|
+
error_ = absl::OkStatus();
|
255
|
+
return out;
|
256
|
+
}
|
220
257
|
|
221
258
|
bool has_error() const { return !error_.ok(); }
|
222
259
|
|
@@ -224,55 +261,31 @@ class HPackParser::Input {
|
|
224
261
|
// chttp2 does not close the connection.
|
225
262
|
// Intended for errors that are specific to a stream and recoverable.
|
226
263
|
// Callers should ensure that any hpack table updates happen.
|
227
|
-
void SetErrorAndContinueParsing(
|
228
|
-
|
229
|
-
|
264
|
+
GPR_ATTRIBUTE_NOINLINE void SetErrorAndContinueParsing(
|
265
|
+
grpc_error_handle error) {
|
266
|
+
GPR_ASSERT(!error.ok());
|
267
|
+
// StreamId is used as a signal to skip this stream but keep the connection
|
268
|
+
// alive
|
269
|
+
SetError(EnsureStreamError(std::move(error)));
|
230
270
|
}
|
231
271
|
|
232
272
|
// Set the current error, and skip past remaining bytes.
|
233
273
|
// Intended for unrecoverable errors, with the expectation that they will
|
234
274
|
// close the connection on return to chttp2.
|
235
|
-
void SetErrorAndStopParsing(
|
236
|
-
|
275
|
+
GPR_ATTRIBUTE_NOINLINE void SetErrorAndStopParsing(grpc_error_handle error) {
|
276
|
+
GPR_ASSERT(!error.ok());
|
237
277
|
SetError(std::move(error));
|
238
278
|
begin_ = end_;
|
239
279
|
}
|
240
280
|
|
241
|
-
// Set the error to an unexpected eof
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
GPR_ASSERT(min_progress_size > 0);
|
246
|
-
if (min_progress_size_ != 0 || error_.connection_error()) {
|
247
|
-
GPR_DEBUG_ASSERT(eof_error());
|
248
|
-
return;
|
249
|
-
}
|
250
|
-
// Set min progress size, taking into account bytes parsed already but not
|
251
|
-
// consumed.
|
252
|
-
min_progress_size_ = min_progress_size + (begin_ - frontier_);
|
253
|
-
GPR_DEBUG_ASSERT(eof_error());
|
281
|
+
// Set the error to an unexpected eof
|
282
|
+
void UnexpectedEOF() {
|
283
|
+
if (!error_.ok() && !IsStreamError(error_)) return;
|
284
|
+
eof_error_ = true;
|
254
285
|
}
|
255
286
|
|
256
287
|
// Update the frontier - signifies we've successfully parsed another element
|
257
|
-
void UpdateFrontier() {
|
258
|
-
GPR_DEBUG_ASSERT(skip_bytes_ == 0);
|
259
|
-
frontier_ = begin_;
|
260
|
-
}
|
261
|
-
|
262
|
-
void UpdateFrontierAndSkipBytes(size_t skip_bytes) {
|
263
|
-
UpdateFrontier();
|
264
|
-
size_t remaining = end_ - begin_;
|
265
|
-
if (skip_bytes >= remaining) {
|
266
|
-
// If we have more bytes to skip than we have remaining in this buffer
|
267
|
-
// then we skip over what's there and stash that we need to skip some
|
268
|
-
// more.
|
269
|
-
skip_bytes_ = skip_bytes - remaining;
|
270
|
-
frontier_ = end_;
|
271
|
-
} else {
|
272
|
-
// Otherwise we zoom through some bytes and continue parsing.
|
273
|
-
frontier_ += skip_bytes_;
|
274
|
-
}
|
275
|
-
}
|
288
|
+
void UpdateFrontier() { frontier_ = begin_; }
|
276
289
|
|
277
290
|
// Get the frontier - for buffering should we fail due to eof
|
278
291
|
const uint8_t* frontier() const { return frontier_; }
|
@@ -281,23 +294,19 @@ class HPackParser::Input {
|
|
281
294
|
// Helper to set the error to out of range for ParseVarint
|
282
295
|
absl::optional<uint32_t> ParseVarintOutOfRange(uint32_t value,
|
283
296
|
uint8_t last_byte) {
|
284
|
-
SetErrorAndStopParsing(
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
// Helper to set the error in the case of a malicious encoding
|
290
|
-
absl::optional<uint32_t> ParseVarintMaliciousEncoding() {
|
291
|
-
SetErrorAndStopParsing(HpackParseResult::MaliciousVarintEncodingError());
|
297
|
+
SetErrorAndStopParsing(absl::InternalError(absl::StrFormat(
|
298
|
+
"integer overflow in hpack integer decoding: have 0x%08x, "
|
299
|
+
"got byte 0x%02x on byte 5",
|
300
|
+
value, last_byte)));
|
292
301
|
return absl::optional<uint32_t>();
|
293
302
|
}
|
294
303
|
|
295
304
|
// If no error is set, set it to the given error (i.e. first error wins)
|
296
305
|
// Do not use this directly, instead use SetErrorAndContinueParsing or
|
297
306
|
// SetErrorAndStopParsing.
|
298
|
-
void SetError(
|
299
|
-
if (!error_.ok() ||
|
300
|
-
if (error
|
307
|
+
void SetError(grpc_error_handle error) {
|
308
|
+
if (!error_.ok() || eof_error_) {
|
309
|
+
if (!IsStreamError(error) && IsStreamError(error_)) {
|
301
310
|
error_ = std::move(error); // connection errors dominate
|
302
311
|
}
|
303
312
|
return;
|
@@ -314,156 +323,211 @@ class HPackParser::Input {
|
|
314
323
|
// Frontier denotes the first byte past successfully processed input
|
315
324
|
const uint8_t* frontier_;
|
316
325
|
// Current error
|
317
|
-
|
318
|
-
// If the error was EOF, we flag it here
|
319
|
-
|
320
|
-
size_t min_progress_size_ = 0;
|
321
|
-
// Number of bytes that should be skipped before parsing resumes.
|
322
|
-
// (We've failed parsing a request for whatever reason, but we're still
|
323
|
-
// continuing the connection so we need to see future opcodes after this bit).
|
324
|
-
size_t skip_bytes_ = 0;
|
326
|
+
grpc_error_handle error_;
|
327
|
+
// If the error was EOF, we flag it here..
|
328
|
+
bool eof_error_ = false;
|
325
329
|
};
|
326
330
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
331
|
+
// Helper to parse a string and turn it into a slice with appropriate memory
|
332
|
+
// management characteristics
|
333
|
+
class HPackParser::String {
|
334
|
+
public:
|
335
|
+
// ParseResult carries both a ParseStatus and the parsed string
|
336
|
+
struct ParseResult;
|
337
|
+
// Result of parsing a string
|
338
|
+
enum class ParseStatus {
|
339
|
+
// Parsed OK
|
340
|
+
kOk,
|
341
|
+
// Parse reached end of the current frame
|
342
|
+
kEof,
|
343
|
+
// Parse failed due to a huffman decode error
|
344
|
+
kParseHuffFailed,
|
345
|
+
// Parse failed due to a base64 decode error
|
346
|
+
kUnbase64Failed,
|
347
|
+
};
|
348
|
+
|
349
|
+
String() : value_(absl::Span<const uint8_t>()) {}
|
350
|
+
String(const String&) = delete;
|
351
|
+
String& operator=(const String&) = delete;
|
352
|
+
String(String&& other) noexcept : value_(std::move(other.value_)) {
|
353
|
+
other.value_ = absl::Span<const uint8_t>();
|
354
|
+
}
|
355
|
+
String& operator=(String&& other) noexcept {
|
356
|
+
value_ = std::move(other.value_);
|
357
|
+
other.value_ = absl::Span<const uint8_t>();
|
358
|
+
return *this;
|
336
359
|
}
|
337
|
-
GPR_UNREACHABLE_CODE(return absl::string_view());
|
338
|
-
}
|
339
360
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
//
|
344
|
-
|
345
|
-
|
346
|
-
|
361
|
+
// Take the value and leave this empty
|
362
|
+
Slice Take();
|
363
|
+
|
364
|
+
// Return a reference to the value as a string view
|
365
|
+
absl::string_view string_view() const {
|
366
|
+
if (auto* p = absl::get_if<Slice>(&value_)) {
|
367
|
+
return p->as_string_view();
|
368
|
+
} else if (auto* p = absl::get_if<absl::Span<const uint8_t>>(&value_)) {
|
369
|
+
return absl::string_view(reinterpret_cast<const char*>(p->data()),
|
370
|
+
p->size());
|
371
|
+
} else if (auto* p = absl::get_if<std::vector<uint8_t>>(&value_)) {
|
372
|
+
return absl::string_view(reinterpret_cast<const char*>(p->data()),
|
373
|
+
p->size());
|
374
|
+
}
|
375
|
+
GPR_UNREACHABLE_CODE(return absl::string_view());
|
347
376
|
}
|
348
|
-
// Grab the byte range, and iterate through it.
|
349
|
-
const uint8_t* p = input->cur_ptr();
|
350
|
-
input->Advance(length);
|
351
|
-
return HuffDecoder<Out>(output, p, p + length).Run()
|
352
|
-
? HpackParseStatus::kOk
|
353
|
-
: HpackParseStatus::kParseHuffFailed;
|
354
|
-
}
|
355
377
|
|
356
|
-
|
357
|
-
|
358
|
-
StringResult(HpackParseStatus status, size_t wire_size, String value)
|
359
|
-
: status(status), wire_size(wire_size), value(std::move(value)) {}
|
360
|
-
HpackParseStatus status;
|
361
|
-
size_t wire_size;
|
362
|
-
String value;
|
363
|
-
};
|
378
|
+
// Parse a non-binary string
|
379
|
+
static ParseResult Parse(Input* input);
|
364
380
|
|
365
|
-
|
366
|
-
|
367
|
-
// Check there's enough bytes
|
368
|
-
if (input->remaining() < length) {
|
369
|
-
input->UnexpectedEOF(/*min_progress_size=*/length);
|
370
|
-
GPR_DEBUG_ASSERT(input->eof_error());
|
371
|
-
return StringResult{HpackParseStatus::kEof, wire_size, String{}};
|
372
|
-
}
|
373
|
-
auto* refcount = input->slice_refcount();
|
374
|
-
auto* p = input->cur_ptr();
|
375
|
-
input->Advance(length);
|
376
|
-
if (refcount != nullptr) {
|
377
|
-
return StringResult{HpackParseStatus::kOk, wire_size,
|
378
|
-
String(refcount, p, p + length)};
|
379
|
-
} else {
|
380
|
-
return StringResult{HpackParseStatus::kOk, wire_size,
|
381
|
-
String(absl::Span<const uint8_t>(p, length))};
|
382
|
-
}
|
383
|
-
}
|
381
|
+
// Parse a binary string
|
382
|
+
static ParseResult ParseBinary(Input* input);
|
384
383
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
384
|
+
private:
|
385
|
+
void AppendBytes(const uint8_t* data, size_t length);
|
386
|
+
explicit String(std::vector<uint8_t> v) : value_(std::move(v)) {}
|
387
|
+
explicit String(absl::Span<const uint8_t> v) : value_(v) {}
|
388
|
+
String(grpc_slice_refcount* r, const uint8_t* begin, const uint8_t* end)
|
389
|
+
: value_(Slice::FromRefcountAndBytes(r, begin, end)) {}
|
390
|
+
|
391
|
+
// Parse some huffman encoded bytes, using output(uint8_t b) to emit each
|
392
|
+
// decoded byte.
|
393
|
+
template <typename Out>
|
394
|
+
static ParseStatus ParseHuff(Input* input, uint32_t length, Out output) {
|
395
|
+
// If there's insufficient bytes remaining, return now.
|
396
|
+
if (input->remaining() < length) {
|
397
|
+
input->UnexpectedEOF();
|
398
|
+
GPR_DEBUG_ASSERT(input->eof_error());
|
399
|
+
return ParseStatus::kEof;
|
400
|
+
}
|
401
|
+
// Grab the byte range, and iterate through it.
|
402
|
+
const uint8_t* p = input->cur_ptr();
|
403
|
+
input->Advance(length);
|
404
|
+
return HuffDecoder<Out>(output, p, p + length).Run()
|
405
|
+
? ParseStatus::kOk
|
406
|
+
: ParseStatus::kParseHuffFailed;
|
389
407
|
}
|
390
408
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
// Decode 4 bytes at a time while we can
|
395
|
-
while (end - cur >= 4) {
|
396
|
-
uint32_t bits = kBase64InverseTable.table[*cur];
|
397
|
-
if (bits > 63) return {};
|
398
|
-
uint32_t buffer = bits << 18;
|
399
|
-
++cur;
|
400
|
-
|
401
|
-
bits = kBase64InverseTable.table[*cur];
|
402
|
-
if (bits > 63) return {};
|
403
|
-
buffer |= bits << 12;
|
404
|
-
++cur;
|
405
|
-
|
406
|
-
bits = kBase64InverseTable.table[*cur];
|
407
|
-
if (bits > 63) return {};
|
408
|
-
buffer |= bits << 6;
|
409
|
-
++cur;
|
410
|
-
|
411
|
-
bits = kBase64InverseTable.table[*cur];
|
412
|
-
if (bits > 63) return {};
|
413
|
-
buffer |= bits;
|
414
|
-
++cur;
|
415
|
-
|
416
|
-
out.insert(out.end(), {static_cast<uint8_t>(buffer >> 16),
|
417
|
-
static_cast<uint8_t>(buffer >> 8),
|
418
|
-
static_cast<uint8_t>(buffer)});
|
419
|
-
}
|
420
|
-
// Deal with the last 0, 1, 2, or 3 bytes.
|
421
|
-
switch (end - cur) {
|
422
|
-
case 0:
|
423
|
-
return out;
|
424
|
-
case 1:
|
425
|
-
return {};
|
426
|
-
case 2: {
|
427
|
-
uint32_t bits = kBase64InverseTable.table[*cur];
|
428
|
-
if (bits > 63) return {};
|
429
|
-
uint32_t buffer = bits << 18;
|
409
|
+
// Parse some uncompressed string bytes.
|
410
|
+
static ParseResult ParseUncompressed(Input* input, uint32_t length,
|
411
|
+
uint32_t wire_size);
|
430
412
|
|
431
|
-
|
432
|
-
|
433
|
-
if (bits > 63) return {};
|
434
|
-
buffer |= bits << 12;
|
413
|
+
// Turn base64 encoded bytes into not base64 encoded bytes.
|
414
|
+
static ParseResult Unbase64(String s);
|
435
415
|
|
436
|
-
|
437
|
-
|
438
|
-
|
416
|
+
// Main loop for Unbase64
|
417
|
+
static absl::optional<std::vector<uint8_t>> Unbase64Loop(const uint8_t* cur,
|
418
|
+
const uint8_t* end) {
|
419
|
+
while (cur != end && end[-1] == '=') {
|
420
|
+
--end;
|
439
421
|
}
|
440
|
-
|
422
|
+
|
423
|
+
std::vector<uint8_t> out;
|
424
|
+
out.reserve(3 * (end - cur) / 4 + 3);
|
425
|
+
|
426
|
+
// Decode 4 bytes at a time while we can
|
427
|
+
while (end - cur >= 4) {
|
441
428
|
uint32_t bits = kBase64InverseTable.table[*cur];
|
442
429
|
if (bits > 63) return {};
|
443
430
|
uint32_t buffer = bits << 18;
|
444
|
-
|
445
431
|
++cur;
|
432
|
+
|
446
433
|
bits = kBase64InverseTable.table[*cur];
|
447
434
|
if (bits > 63) return {};
|
448
435
|
buffer |= bits << 12;
|
449
|
-
|
450
436
|
++cur;
|
437
|
+
|
451
438
|
bits = kBase64InverseTable.table[*cur];
|
452
439
|
if (bits > 63) return {};
|
453
440
|
buffer |= bits << 6;
|
441
|
+
++cur;
|
454
442
|
|
443
|
+
bits = kBase64InverseTable.table[*cur];
|
444
|
+
if (bits > 63) return {};
|
445
|
+
buffer |= bits;
|
455
446
|
++cur;
|
456
|
-
|
457
|
-
out.
|
458
|
-
|
459
|
-
|
447
|
+
|
448
|
+
out.insert(out.end(), {static_cast<uint8_t>(buffer >> 16),
|
449
|
+
static_cast<uint8_t>(buffer >> 8),
|
450
|
+
static_cast<uint8_t>(buffer)});
|
460
451
|
}
|
452
|
+
// Deal with the last 0, 1, 2, or 3 bytes.
|
453
|
+
switch (end - cur) {
|
454
|
+
case 0:
|
455
|
+
return out;
|
456
|
+
case 1:
|
457
|
+
return {};
|
458
|
+
case 2: {
|
459
|
+
uint32_t bits = kBase64InverseTable.table[*cur];
|
460
|
+
if (bits > 63) return {};
|
461
|
+
uint32_t buffer = bits << 18;
|
462
|
+
|
463
|
+
++cur;
|
464
|
+
bits = kBase64InverseTable.table[*cur];
|
465
|
+
if (bits > 63) return {};
|
466
|
+
buffer |= bits << 12;
|
467
|
+
|
468
|
+
if (buffer & 0xffff) return {};
|
469
|
+
out.push_back(static_cast<uint8_t>(buffer >> 16));
|
470
|
+
return out;
|
471
|
+
}
|
472
|
+
case 3: {
|
473
|
+
uint32_t bits = kBase64InverseTable.table[*cur];
|
474
|
+
if (bits > 63) return {};
|
475
|
+
uint32_t buffer = bits << 18;
|
476
|
+
|
477
|
+
++cur;
|
478
|
+
bits = kBase64InverseTable.table[*cur];
|
479
|
+
if (bits > 63) return {};
|
480
|
+
buffer |= bits << 12;
|
481
|
+
|
482
|
+
++cur;
|
483
|
+
bits = kBase64InverseTable.table[*cur];
|
484
|
+
if (bits > 63) return {};
|
485
|
+
buffer |= bits << 6;
|
486
|
+
|
487
|
+
++cur;
|
488
|
+
if (buffer & 0xff) return {};
|
489
|
+
out.push_back(static_cast<uint8_t>(buffer >> 16));
|
490
|
+
out.push_back(static_cast<uint8_t>(buffer >> 8));
|
491
|
+
return out;
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
GPR_UNREACHABLE_CODE(return out;);
|
461
496
|
}
|
462
497
|
|
463
|
-
|
498
|
+
absl::variant<Slice, absl::Span<const uint8_t>, std::vector<uint8_t>> value_;
|
499
|
+
};
|
500
|
+
|
501
|
+
struct HPackParser::String::ParseResult {
|
502
|
+
ParseResult() = delete;
|
503
|
+
ParseResult(ParseStatus status, size_t wire_size, String value)
|
504
|
+
: status(status), wire_size(wire_size), value(std::move(value)) {}
|
505
|
+
ParseStatus status;
|
506
|
+
size_t wire_size;
|
507
|
+
String value;
|
508
|
+
};
|
509
|
+
|
510
|
+
HPackParser::String::ParseResult HPackParser::String::ParseUncompressed(
|
511
|
+
Input* input, uint32_t length, uint32_t wire_size) {
|
512
|
+
// Check there's enough bytes
|
513
|
+
if (input->remaining() < length) {
|
514
|
+
input->UnexpectedEOF();
|
515
|
+
GPR_DEBUG_ASSERT(input->eof_error());
|
516
|
+
return ParseResult{ParseStatus::kEof, wire_size, String{}};
|
517
|
+
}
|
518
|
+
auto* refcount = input->slice_refcount();
|
519
|
+
auto* p = input->cur_ptr();
|
520
|
+
input->Advance(length);
|
521
|
+
if (refcount != nullptr) {
|
522
|
+
return ParseResult{ParseStatus::kOk, wire_size,
|
523
|
+
String(refcount, p, p + length)};
|
524
|
+
} else {
|
525
|
+
return ParseResult{ParseStatus::kOk, wire_size,
|
526
|
+
String(absl::Span<const uint8_t>(p, length))};
|
527
|
+
}
|
464
528
|
}
|
465
529
|
|
466
|
-
HPackParser::String::
|
530
|
+
HPackParser::String::ParseResult HPackParser::String::Unbase64(String s) {
|
467
531
|
absl::optional<std::vector<uint8_t>> result;
|
468
532
|
if (auto* p = absl::get_if<Slice>(&s.value_)) {
|
469
533
|
result = Unbase64Loop(p->begin(), p->end());
|
@@ -475,38 +539,46 @@ HPackParser::String::StringResult HPackParser::String::Unbase64(String s) {
|
|
475
539
|
result = Unbase64Loop(p->data(), p->data() + p->size());
|
476
540
|
}
|
477
541
|
if (!result.has_value()) {
|
478
|
-
return
|
479
|
-
|
542
|
+
return ParseResult{ParseStatus::kUnbase64Failed, s.string_view().length(),
|
543
|
+
String{}};
|
480
544
|
}
|
481
|
-
return
|
482
|
-
|
545
|
+
return ParseResult{ParseStatus::kOk, s.string_view().length(),
|
546
|
+
String(std::move(*result))};
|
483
547
|
}
|
484
548
|
|
485
|
-
HPackParser::String::
|
486
|
-
|
487
|
-
|
488
|
-
|
549
|
+
HPackParser::String::ParseResult HPackParser::String::Parse(Input* input) {
|
550
|
+
auto pfx = input->ParseStringPrefix();
|
551
|
+
if (!pfx.has_value()) {
|
552
|
+
GPR_DEBUG_ASSERT(input->eof_error());
|
553
|
+
return ParseResult{ParseStatus::kEof, 0, String{}};
|
554
|
+
}
|
555
|
+
if (pfx->huff) {
|
489
556
|
// Huffman coded
|
490
557
|
std::vector<uint8_t> output;
|
491
|
-
|
492
|
-
|
558
|
+
ParseStatus sts = ParseHuff(input, pfx->length,
|
559
|
+
[&output](uint8_t c) { output.push_back(c); });
|
493
560
|
size_t wire_len = output.size();
|
494
|
-
return
|
561
|
+
return ParseResult{sts, wire_len, String(std::move(output))};
|
495
562
|
}
|
496
|
-
return ParseUncompressed(input, length, length);
|
563
|
+
return ParseUncompressed(input, pfx->length, pfx->length);
|
497
564
|
}
|
498
565
|
|
499
|
-
HPackParser::String::
|
500
|
-
Input* input
|
501
|
-
|
502
|
-
|
566
|
+
HPackParser::String::ParseResult HPackParser::String::ParseBinary(
|
567
|
+
Input* input) {
|
568
|
+
auto pfx = input->ParseStringPrefix();
|
569
|
+
if (!pfx.has_value()) {
|
570
|
+
GPR_DEBUG_ASSERT(input->eof_error());
|
571
|
+
return ParseResult{ParseStatus::kEof, 0, String{}};
|
572
|
+
}
|
573
|
+
if (!pfx->huff) {
|
574
|
+
if (pfx->length > 0 && input->peek() == 0) {
|
503
575
|
// 'true-binary'
|
504
576
|
input->Advance(1);
|
505
|
-
return ParseUncompressed(input, length - 1, length);
|
577
|
+
return ParseUncompressed(input, pfx->length - 1, pfx->length);
|
506
578
|
}
|
507
579
|
// Base64 encoded... pull out the string, then unbase64 it
|
508
|
-
auto base64 = ParseUncompressed(input, length, length);
|
509
|
-
if (base64.status !=
|
580
|
+
auto base64 = ParseUncompressed(input, pfx->length, pfx->length);
|
581
|
+
if (base64.status != ParseStatus::kOk) return base64;
|
510
582
|
return Unbase64(std::move(base64.value));
|
511
583
|
} else {
|
512
584
|
// Huffman encoded...
|
@@ -515,35 +587,36 @@ HPackParser::String::StringResult HPackParser::String::ParseBinary(
|
|
515
587
|
// and what is it.
|
516
588
|
enum class State { kUnsure, kBinary, kBase64 };
|
517
589
|
State state = State::kUnsure;
|
518
|
-
auto sts =
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
590
|
+
auto sts =
|
591
|
+
ParseHuff(input, pfx->length, [&state, &decompressed](uint8_t c) {
|
592
|
+
if (state == State::kUnsure) {
|
593
|
+
// First byte... if it's zero it's binary
|
594
|
+
if (c == 0) {
|
595
|
+
// Save the type, and skip the zero
|
596
|
+
state = State::kBinary;
|
597
|
+
return;
|
598
|
+
} else {
|
599
|
+
// Flag base64, store this value
|
600
|
+
state = State::kBase64;
|
601
|
+
}
|
602
|
+
}
|
603
|
+
// Non-first byte, or base64 first byte
|
604
|
+
decompressed.push_back(c);
|
605
|
+
});
|
606
|
+
if (sts != ParseStatus::kOk) {
|
607
|
+
return ParseResult{sts, 0, String{}};
|
535
608
|
}
|
536
609
|
switch (state) {
|
537
610
|
case State::kUnsure:
|
538
611
|
// No bytes, empty span
|
539
|
-
return
|
540
|
-
|
612
|
+
return ParseResult{ParseStatus::kOk, 0,
|
613
|
+
String(absl::Span<const uint8_t>())};
|
541
614
|
case State::kBinary:
|
542
615
|
// Binary, we're done
|
543
616
|
{
|
544
617
|
size_t wire_len = decompressed.size();
|
545
|
-
return
|
546
|
-
|
618
|
+
return ParseResult{ParseStatus::kOk, wire_len,
|
619
|
+
String(std::move(decompressed))};
|
547
620
|
}
|
548
621
|
case State::kBase64:
|
549
622
|
// Base64 - unpack it
|
@@ -556,38 +629,28 @@ HPackParser::String::StringResult HPackParser::String::ParseBinary(
|
|
556
629
|
// Parser parses one key/value pair from a byte stream.
|
557
630
|
class HPackParser::Parser {
|
558
631
|
public:
|
559
|
-
Parser(Input* input, grpc_metadata_batch
|
560
|
-
|
632
|
+
Parser(Input* input, grpc_metadata_batch* metadata_buffer, HPackTable* table,
|
633
|
+
uint8_t* dynamic_table_updates_allowed, uint32_t* frame_length,
|
634
|
+
RandomEarlyDetection* metadata_early_detection, LogInfo log_info)
|
561
635
|
: input_(input),
|
562
636
|
metadata_buffer_(metadata_buffer),
|
563
|
-
|
637
|
+
table_(table),
|
638
|
+
dynamic_table_updates_allowed_(dynamic_table_updates_allowed),
|
639
|
+
frame_length_(frame_length),
|
640
|
+
metadata_early_detection_(metadata_early_detection),
|
564
641
|
log_info_(log_info) {}
|
565
642
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
return ParseKeyLength();
|
572
|
-
case ParseState::kParsingKeyBody:
|
573
|
-
return ParseKeyBody();
|
574
|
-
case ParseState::kSkippingKeyBody:
|
575
|
-
return SkipKeyBody();
|
576
|
-
case ParseState::kParsingValueLength:
|
577
|
-
return ParseValueLength();
|
578
|
-
case ParseState::kParsingValueBody:
|
579
|
-
return ParseValueBody();
|
580
|
-
case ParseState::kSkippingValueLength:
|
581
|
-
return SkipValueLength();
|
582
|
-
case ParseState::kSkippingValueBody:
|
583
|
-
return SkipValueBody();
|
643
|
+
// Skip any priority bits, or return false on failure
|
644
|
+
bool SkipPriority() {
|
645
|
+
if (input_->remaining() < 5) {
|
646
|
+
input_->UnexpectedEOF();
|
647
|
+
return false;
|
584
648
|
}
|
585
|
-
|
649
|
+
input_->Advance(5);
|
650
|
+
return true;
|
586
651
|
}
|
587
652
|
|
588
|
-
|
589
|
-
bool ParseTop() {
|
590
|
-
GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop);
|
653
|
+
bool Parse() {
|
591
654
|
auto cur = *input_->Next();
|
592
655
|
switch (cur >> 4) {
|
593
656
|
// Literal header not indexed - First byte format: 0000xxxx
|
@@ -600,11 +663,11 @@ class HPackParser::Parser {
|
|
600
663
|
case 1:
|
601
664
|
switch (cur & 0xf) {
|
602
665
|
case 0: // literal key
|
603
|
-
return
|
666
|
+
return FinishHeaderOmitFromTable(ParseLiteralKey());
|
604
667
|
case 0xf: // varint encoded key index
|
605
|
-
return
|
668
|
+
return FinishHeaderOmitFromTable(ParseVarIdxKey(0xf));
|
606
669
|
default: // inline encoded key index
|
607
|
-
return
|
670
|
+
return FinishHeaderOmitFromTable(ParseIdxKey(cur & 0xf));
|
608
671
|
}
|
609
672
|
// Update max table size.
|
610
673
|
// First byte format: 001xxxxx
|
@@ -631,20 +694,20 @@ class HPackParser::Parser {
|
|
631
694
|
case 4:
|
632
695
|
if (cur == 0x40) {
|
633
696
|
// literal key
|
634
|
-
return
|
697
|
+
return FinishHeaderAndAddToTable(ParseLiteralKey());
|
635
698
|
}
|
636
699
|
ABSL_FALLTHROUGH_INTENDED;
|
637
700
|
case 5:
|
638
701
|
case 6:
|
639
702
|
// inline encoded key index
|
640
|
-
return
|
703
|
+
return FinishHeaderAndAddToTable(ParseIdxKey(cur & 0x3f));
|
641
704
|
case 7:
|
642
705
|
if (cur == 0x7f) {
|
643
706
|
// varint encoded key index
|
644
|
-
return
|
707
|
+
return FinishHeaderAndAddToTable(ParseVarIdxKey(0x3f));
|
645
708
|
} else {
|
646
709
|
// inline encoded key index
|
647
|
-
return
|
710
|
+
return FinishHeaderAndAddToTable(ParseIdxKey(cur & 0x3f));
|
648
711
|
}
|
649
712
|
// Indexed Header Field Representation
|
650
713
|
// First byte format: 1xxxxxxx
|
@@ -656,7 +719,7 @@ class HPackParser::Parser {
|
|
656
719
|
if (cur == 0x80) {
|
657
720
|
// illegal value.
|
658
721
|
input_->SetErrorAndStopParsing(
|
659
|
-
|
722
|
+
absl::InternalError("Illegal hpack op code"));
|
660
723
|
return false;
|
661
724
|
}
|
662
725
|
ABSL_FALLTHROUGH_INTENDED;
|
@@ -680,6 +743,7 @@ class HPackParser::Parser {
|
|
680
743
|
GPR_UNREACHABLE_CODE(abort());
|
681
744
|
}
|
682
745
|
|
746
|
+
private:
|
683
747
|
void GPR_ATTRIBUTE_NOINLINE LogHeader(const HPackTable::Memento& memento) {
|
684
748
|
const char* type;
|
685
749
|
switch (log_info_.type) {
|
@@ -693,48 +757,46 @@ class HPackParser::Parser {
|
|
693
757
|
type = "???";
|
694
758
|
break;
|
695
759
|
}
|
696
|
-
gpr_log(
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
760
|
+
gpr_log(GPR_DEBUG, "HTTP:%d:%s:%s: %s%s", log_info_.stream_id, type,
|
761
|
+
log_info_.is_client ? "CLI" : "SVR",
|
762
|
+
memento.md.DebugString().c_str(),
|
763
|
+
memento.parse_status.ok()
|
764
|
+
? ""
|
765
|
+
: absl::StrCat(
|
766
|
+
" (parse error: ", memento.parse_status.ToString(), ")")
|
767
|
+
.c_str());
|
704
768
|
}
|
705
769
|
|
706
770
|
void EmitHeader(const HPackTable::Memento& md) {
|
707
771
|
// Pass up to the transport
|
708
|
-
|
772
|
+
*frame_length_ += md.md.transport_size();
|
773
|
+
if (!input_->has_error() &&
|
774
|
+
metadata_early_detection_->MustReject(*frame_length_)) {
|
775
|
+
// Reject any requests above hard metadata limit.
|
776
|
+
HandleMetadataHardSizeLimitExceeded(md);
|
777
|
+
}
|
709
778
|
if (!md.parse_status.ok()) {
|
710
779
|
// Reject any requests with invalid metadata.
|
711
|
-
|
780
|
+
HandleMetadataParseError(md.parse_status);
|
712
781
|
}
|
713
782
|
if (GPR_LIKELY(metadata_buffer_ != nullptr)) {
|
714
783
|
metadata_buffer_->Set(md.md);
|
715
784
|
}
|
716
|
-
if (state_.metadata_early_detection.MustReject(state_.frame_length)) {
|
717
|
-
// Reject any requests above hard metadata limit.
|
718
|
-
input_->SetErrorAndContinueParsing(
|
719
|
-
HpackParseResult::HardMetadataLimitExceededError(
|
720
|
-
std::exchange(metadata_buffer_, nullptr), state_.frame_length,
|
721
|
-
state_.metadata_early_detection.hard_limit()));
|
722
|
-
}
|
723
785
|
}
|
724
786
|
|
725
|
-
bool FinishHeaderAndAddToTable(HPackTable::Memento md) {
|
787
|
+
bool FinishHeaderAndAddToTable(absl::optional<HPackTable::Memento> md) {
|
788
|
+
// Allow higher code to just pass in failures ... simplifies things a bit.
|
789
|
+
if (!md.has_value()) return false;
|
726
790
|
// Log if desired
|
727
791
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_chttp2_hpack_parser)) {
|
728
|
-
LogHeader(md);
|
792
|
+
LogHeader(*md);
|
729
793
|
}
|
730
794
|
// Emit whilst we own the metadata.
|
731
|
-
EmitHeader(md);
|
795
|
+
EmitHeader(*md);
|
732
796
|
// Add to the hpack table
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
state_.hpack_table.current_table_bytes(),
|
737
|
-
state_.hpack_table.max_bytes()));
|
797
|
+
grpc_error_handle err = table_->Add(std::move(*md));
|
798
|
+
if (GPR_UNLIKELY(!err.ok())) {
|
799
|
+
input_->SetErrorAndStopParsing(std::move(err));
|
738
800
|
return false;
|
739
801
|
};
|
740
802
|
return true;
|
@@ -755,269 +817,136 @@ class HPackParser::Parser {
|
|
755
817
|
EmitHeader(md);
|
756
818
|
}
|
757
819
|
|
758
|
-
//
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop);
|
777
|
-
auto index = input_->ParseVarint(offset);
|
778
|
-
if (GPR_UNLIKELY(!index.has_value())) return false;
|
779
|
-
return StartIdxKey(*index, add_to_table);
|
780
|
-
}
|
781
|
-
|
782
|
-
bool StartParseLiteralKey(bool add_to_table) {
|
783
|
-
GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop);
|
784
|
-
state_.add_to_table = add_to_table;
|
785
|
-
state_.parse_state = ParseState::kParsingKeyLength;
|
786
|
-
input_->UpdateFrontier();
|
787
|
-
return ParseKeyLength();
|
788
|
-
}
|
789
|
-
|
790
|
-
bool ShouldSkipParsingString(uint64_t string_length) const {
|
791
|
-
// We skip parsing if the string is longer than the current table size, and
|
792
|
-
// if we would have to reject the string due to metadata length limits
|
793
|
-
// regardless of what else was in the metadata batch.
|
794
|
-
//
|
795
|
-
// Why longer than the current table size? - it simplifies the logic at the
|
796
|
-
// end of skipping the string (and possibly a second if this is a key).
|
797
|
-
// If a key/value pair longer than the current table size is added to the
|
798
|
-
// hpack table we're forced to clear the entire table - this is a
|
799
|
-
// predictable operation that's easy to encode and doesn't need any state
|
800
|
-
// other than "skipping" to be carried forward.
|
801
|
-
// If we did not do this, we could end up in a situation where even though
|
802
|
-
// the metadata would overflow the current limit, it might not overflow the
|
803
|
-
// current hpack table size, and so we could not skip in on the off chance
|
804
|
-
// that we'd need to add it to the hpack table *and* reject the batch as a
|
805
|
-
// whole.
|
806
|
-
// That would be a mess, we're not doing it.
|
807
|
-
//
|
808
|
-
// These rules will end up having us parse some things that ultimately get
|
809
|
-
// rejected, and that's ok: the important thing is to have a bounded maximum
|
810
|
-
// so we can't be forced to infinitely buffer - not to have a perfect
|
811
|
-
// computation here.
|
812
|
-
return string_length > state_.hpack_table.current_table_size() &&
|
813
|
-
state_.metadata_early_detection.MustReject(
|
814
|
-
string_length + hpack_constants::kEntryOverhead);
|
815
|
-
}
|
816
|
-
|
817
|
-
bool ParseKeyLength() {
|
818
|
-
GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kParsingKeyLength);
|
819
|
-
auto pfx = input_->ParseStringPrefix();
|
820
|
-
if (!pfx.has_value()) return false;
|
821
|
-
state_.is_string_huff_compressed = pfx->huff;
|
822
|
-
state_.string_length = pfx->length;
|
823
|
-
input_->UpdateFrontier();
|
824
|
-
if (ShouldSkipParsingString(state_.string_length)) {
|
825
|
-
input_->SetErrorAndContinueParsing(
|
826
|
-
HpackParseResult::HardMetadataLimitExceededByKeyError(
|
827
|
-
state_.string_length,
|
828
|
-
state_.metadata_early_detection.hard_limit()));
|
829
|
-
metadata_buffer_ = nullptr;
|
830
|
-
state_.parse_state = ParseState::kSkippingKeyBody;
|
831
|
-
return SkipKeyBody();
|
832
|
-
} else {
|
833
|
-
state_.parse_state = ParseState::kParsingKeyBody;
|
834
|
-
return ParseKeyBody();
|
835
|
-
}
|
836
|
-
}
|
837
|
-
|
838
|
-
bool ParseKeyBody() {
|
839
|
-
GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kParsingKeyBody);
|
840
|
-
auto key = String::Parse(input_, state_.is_string_huff_compressed,
|
841
|
-
state_.string_length);
|
842
|
-
switch (key.status) {
|
843
|
-
case HpackParseStatus::kOk:
|
844
|
-
break;
|
845
|
-
case HpackParseStatus::kEof:
|
846
|
-
GPR_DEBUG_ASSERT(input_->eof_error());
|
847
|
-
return false;
|
848
|
-
default:
|
849
|
-
input_->SetErrorAndStopParsing(
|
850
|
-
HpackParseResult::FromStatus(key.status));
|
851
|
-
return false;
|
820
|
+
// Helper type to build a memento from a key & value, and to consolidate some
|
821
|
+
// tricky error path code.
|
822
|
+
class MementoBuilder {
|
823
|
+
public:
|
824
|
+
explicit MementoBuilder(Input* input, absl::string_view key_string,
|
825
|
+
absl::Status status = absl::OkStatus())
|
826
|
+
: input_(input), key_string_(key_string), status_(std::move(status)) {}
|
827
|
+
|
828
|
+
auto ErrorHandler() {
|
829
|
+
return [this](absl::string_view error, const Slice&) {
|
830
|
+
auto message =
|
831
|
+
absl::StrCat("Error parsing '", key_string_,
|
832
|
+
"' metadata: error=", error, " key=", key_string_);
|
833
|
+
gpr_log(GPR_ERROR, "%s", message.c_str());
|
834
|
+
if (status_.ok()) {
|
835
|
+
status_ = absl::InternalError(message);
|
836
|
+
}
|
837
|
+
};
|
852
838
|
}
|
853
|
-
input_->UpdateFrontier();
|
854
|
-
state_.parse_state = ParseState::kParsingValueLength;
|
855
|
-
state_.is_binary_header = absl::EndsWith(key.value.string_view(), "-bin");
|
856
|
-
state_.key.emplace<Slice>(key.value.Take());
|
857
|
-
return ParseValueLength();
|
858
|
-
}
|
859
839
|
|
860
|
-
|
861
|
-
|
862
|
-
if (remaining >= state_.string_length) {
|
863
|
-
input_->Advance(state_.string_length);
|
864
|
-
return true;
|
865
|
-
} else {
|
866
|
-
input_->Advance(remaining);
|
867
|
-
input_->UpdateFrontier();
|
868
|
-
state_.string_length -= remaining;
|
869
|
-
// The default action of our outer loop is to buffer up to
|
870
|
-
// min_progress_size bytes.
|
871
|
-
// We know we need to do nothing up to the string length, so it would be
|
872
|
-
// legal to pass that here - however that would cause a client selected
|
873
|
-
// large buffer size to be accumulated, which would be an attack vector.
|
874
|
-
// We could also pass 1 here, and we'd be called to parse potentially
|
875
|
-
// every byte, which would give clients a way to consume substantial CPU -
|
876
|
-
// again not great.
|
877
|
-
// So we pick some tradeoff number - big enough to amortize wakeups, but
|
878
|
-
// probably not big enough to cause excessive memory use on the receiver.
|
879
|
-
input_->UnexpectedEOF(
|
880
|
-
/*min_progress_size=*/std::min(state_.string_length, 1024u));
|
881
|
-
return false;
|
840
|
+
HPackTable::Memento Build(ParsedMetadata<grpc_metadata_batch> memento) {
|
841
|
+
return HPackTable::Memento{std::move(memento), std::move(status_)};
|
882
842
|
}
|
883
|
-
}
|
884
|
-
|
885
|
-
bool SkipKeyBody() {
|
886
|
-
GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kSkippingKeyBody);
|
887
|
-
if (!SkipStringBody()) return false;
|
888
|
-
input_->UpdateFrontier();
|
889
|
-
state_.parse_state = ParseState::kSkippingValueLength;
|
890
|
-
return SkipValueLength();
|
891
|
-
}
|
892
843
|
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
844
|
+
// Handle the result of parsing a value.
|
845
|
+
// Returns true if parsing should continue, false if it should stop.
|
846
|
+
// Stores an error on the input if necessary.
|
847
|
+
bool HandleParseResult(String::ParseStatus status) {
|
848
|
+
auto continuable = [this](absl::string_view error) {
|
849
|
+
auto this_error = absl::InternalError(absl::StrCat(
|
850
|
+
"Error parsing '", key_string_, "' metadata: error=", error));
|
851
|
+
if (status_.ok()) status_ = this_error;
|
852
|
+
input_->SetErrorAndContinueParsing(std::move(this_error));
|
853
|
+
};
|
854
|
+
switch (status) {
|
855
|
+
case String::ParseStatus::kOk:
|
856
|
+
return true;
|
857
|
+
case String::ParseStatus::kParseHuffFailed:
|
858
|
+
input_->SetErrorAndStopParsing(
|
859
|
+
absl::InternalError("Huffman decoding failed"));
|
860
|
+
return false;
|
861
|
+
case String::ParseStatus::kUnbase64Failed:
|
862
|
+
continuable("illegal base64 encoding");
|
863
|
+
return true;
|
864
|
+
case String::ParseStatus::kEof:
|
865
|
+
GPR_DEBUG_ASSERT(input_->eof_error());
|
866
|
+
return false;
|
867
|
+
}
|
868
|
+
GPR_UNREACHABLE_CODE(return false);
|
910
869
|
}
|
911
|
-
return true;
|
912
|
-
}
|
913
870
|
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
state_.string_length = pfx->length;
|
920
|
-
input_->UpdateFrontier();
|
921
|
-
if (ShouldSkipParsingString(state_.string_length)) {
|
922
|
-
input_->SetErrorAndContinueParsing(
|
923
|
-
HpackParseResult::HardMetadataLimitExceededByValueError(
|
924
|
-
Match(
|
925
|
-
state_.key, [](const Slice& s) { return s.as_string_view(); },
|
926
|
-
[](const HPackTable::Memento* m) { return m->md.key(); }),
|
927
|
-
state_.string_length,
|
928
|
-
state_.metadata_early_detection.hard_limit()));
|
929
|
-
metadata_buffer_ = nullptr;
|
930
|
-
state_.parse_state = ParseState::kSkippingValueBody;
|
931
|
-
return SkipValueBody();
|
932
|
-
} else {
|
933
|
-
state_.parse_state = ParseState::kParsingValueBody;
|
934
|
-
return ParseValueBody();
|
935
|
-
}
|
936
|
-
}
|
871
|
+
private:
|
872
|
+
Input* input_;
|
873
|
+
absl::string_view key_string_;
|
874
|
+
absl::Status status_;
|
875
|
+
};
|
937
876
|
|
938
|
-
|
939
|
-
|
940
|
-
auto
|
941
|
-
|
942
|
-
|
943
|
-
state_.string_length)
|
944
|
-
: String::Parse(input_, state_.is_string_huff_compressed,
|
945
|
-
state_.string_length);
|
946
|
-
HpackParseResult& status = state_.frame_error;
|
947
|
-
absl::string_view key_string;
|
948
|
-
if (auto* s = absl::get_if<Slice>(&state_.key)) {
|
949
|
-
key_string = s->as_string_view();
|
950
|
-
if (status.ok()) {
|
951
|
-
auto r = ValidateKey(key_string);
|
952
|
-
if (r != ValidateMetadataResult::kOk) {
|
953
|
-
input_->SetErrorAndContinueParsing(
|
954
|
-
HpackParseResult::InvalidMetadataError(r, key_string));
|
955
|
-
}
|
956
|
-
}
|
957
|
-
} else {
|
958
|
-
const auto* memento = absl::get<const HPackTable::Memento*>(state_.key);
|
959
|
-
key_string = memento->md.key();
|
960
|
-
if (status.ok() && !memento->parse_status.ok()) {
|
961
|
-
input_->SetErrorAndContinueParsing(memento->parse_status);
|
962
|
-
}
|
963
|
-
}
|
964
|
-
switch (value.status) {
|
965
|
-
case HpackParseStatus::kOk:
|
877
|
+
// Parse a string encoded key and a string encoded value
|
878
|
+
absl::optional<HPackTable::Memento> ParseLiteralKey() {
|
879
|
+
auto key = String::Parse(input_);
|
880
|
+
switch (key.status) {
|
881
|
+
case String::ParseStatus::kOk:
|
966
882
|
break;
|
967
|
-
case
|
883
|
+
case String::ParseStatus::kParseHuffFailed:
|
884
|
+
input_->SetErrorAndStopParsing(
|
885
|
+
absl::InternalError("Huffman decoding failed"));
|
886
|
+
return absl::nullopt;
|
887
|
+
case String::ParseStatus::kUnbase64Failed:
|
888
|
+
Crash("unreachable");
|
889
|
+
case String::ParseStatus::kEof:
|
968
890
|
GPR_DEBUG_ASSERT(input_->eof_error());
|
969
|
-
return
|
970
|
-
default: {
|
971
|
-
auto result =
|
972
|
-
HpackParseResult::FromStatusWithKey(value.status, key_string);
|
973
|
-
if (result.stream_error()) {
|
974
|
-
input_->SetErrorAndContinueParsing(std::move(result));
|
975
|
-
break;
|
976
|
-
} else {
|
977
|
-
input_->SetErrorAndStopParsing(std::move(result));
|
978
|
-
return false;
|
979
|
-
}
|
980
|
-
}
|
891
|
+
return absl::nullopt;
|
981
892
|
}
|
893
|
+
auto key_string = key.value.string_view();
|
894
|
+
auto value = ParseValueString(absl::EndsWith(key_string, "-bin"));
|
895
|
+
MementoBuilder builder(input_, key_string,
|
896
|
+
EnsureStreamError(ValidateKey(key_string)));
|
897
|
+
if (!builder.HandleParseResult(value.status)) return absl::nullopt;
|
982
898
|
auto value_slice = value.value.Take();
|
983
899
|
const auto transport_size =
|
984
900
|
key_string.size() + value.wire_size + hpack_constants::kEntryOverhead;
|
985
|
-
|
986
|
-
key_string, std::move(value_slice),
|
987
|
-
|
988
|
-
if (!status.ok()) return;
|
989
|
-
input_->SetErrorAndContinueParsing(
|
990
|
-
HpackParseResult::MetadataParseError(key_string));
|
991
|
-
gpr_log(GPR_ERROR, "Error parsing '%s' metadata: %s",
|
992
|
-
std::string(key_string).c_str(),
|
993
|
-
std::string(message).c_str());
|
994
|
-
});
|
995
|
-
HPackTable::Memento memento{std::move(md),
|
996
|
-
status.PersistentStreamErrorOrOk()};
|
997
|
-
input_->UpdateFrontier();
|
998
|
-
state_.parse_state = ParseState::kTop;
|
999
|
-
if (state_.add_to_table) {
|
1000
|
-
return FinishHeaderAndAddToTable(std::move(memento));
|
1001
|
-
} else {
|
1002
|
-
FinishHeaderOmitFromTable(memento);
|
1003
|
-
return true;
|
1004
|
-
}
|
901
|
+
return builder.Build(
|
902
|
+
grpc_metadata_batch::Parse(key_string, std::move(value_slice),
|
903
|
+
transport_size, builder.ErrorHandler()));
|
1005
904
|
}
|
1006
905
|
|
1007
|
-
|
906
|
+
absl::Status ValidateKey(absl::string_view key) {
|
1008
907
|
if (key == HttpSchemeMetadata::key() || key == HttpMethodMetadata::key() ||
|
1009
908
|
key == HttpAuthorityMetadata::key() || key == HttpPathMetadata::key() ||
|
1010
909
|
key == HttpStatusMetadata::key()) {
|
1011
|
-
return
|
910
|
+
return absl::OkStatus();
|
1012
911
|
}
|
1013
912
|
return ValidateHeaderKeyIsLegal(key);
|
1014
913
|
}
|
1015
914
|
|
915
|
+
// Parse an index encoded key and a string encoded value
|
916
|
+
absl::optional<HPackTable::Memento> ParseIdxKey(uint32_t index) {
|
917
|
+
const auto* elem = table_->Lookup(index);
|
918
|
+
if (GPR_UNLIKELY(elem == nullptr)) {
|
919
|
+
InvalidHPackIndexError(index);
|
920
|
+
return absl::optional<HPackTable::Memento>();
|
921
|
+
}
|
922
|
+
MementoBuilder builder(input_, elem->md.key(), elem->parse_status);
|
923
|
+
auto value = ParseValueString(elem->md.is_binary_header());
|
924
|
+
if (!builder.HandleParseResult(value.status)) return absl::nullopt;
|
925
|
+
return builder.Build(elem->md.WithNewValue(
|
926
|
+
value.value.Take(), value.wire_size, builder.ErrorHandler()));
|
927
|
+
};
|
928
|
+
|
929
|
+
// Parse a varint index encoded key and a string encoded value
|
930
|
+
absl::optional<HPackTable::Memento> ParseVarIdxKey(uint32_t offset) {
|
931
|
+
auto index = input_->ParseVarint(offset);
|
932
|
+
if (GPR_UNLIKELY(!index.has_value())) return absl::nullopt;
|
933
|
+
return ParseIdxKey(*index);
|
934
|
+
}
|
935
|
+
|
936
|
+
// Parse a string, figuring out if it's binary or not by the key name.
|
937
|
+
String::ParseResult ParseValueString(bool is_binary) {
|
938
|
+
if (is_binary) {
|
939
|
+
return String::ParseBinary(input_);
|
940
|
+
} else {
|
941
|
+
return String::Parse(input_);
|
942
|
+
}
|
943
|
+
}
|
944
|
+
|
1016
945
|
// Emit an indexed field
|
1017
946
|
bool FinishIndexed(absl::optional<uint32_t> index) {
|
1018
|
-
|
947
|
+
*dynamic_table_updates_allowed_ = 0;
|
1019
948
|
if (!index.has_value()) return false;
|
1020
|
-
const auto* elem =
|
949
|
+
const auto* elem = table_->Lookup(*index);
|
1021
950
|
if (GPR_UNLIKELY(elem == nullptr)) {
|
1022
951
|
InvalidHPackIndexError(*index);
|
1023
952
|
return false;
|
@@ -1029,16 +958,15 @@ class HPackParser::Parser {
|
|
1029
958
|
// finish parsing a max table size change
|
1030
959
|
bool FinishMaxTableSize(absl::optional<uint32_t> size) {
|
1031
960
|
if (!size.has_value()) return false;
|
1032
|
-
if (
|
1033
|
-
input_->SetErrorAndStopParsing(
|
1034
|
-
|
961
|
+
if (*dynamic_table_updates_allowed_ == 0) {
|
962
|
+
input_->SetErrorAndStopParsing(absl::InternalError(
|
963
|
+
"More than two max table size changes in a single frame"));
|
1035
964
|
return false;
|
1036
965
|
}
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
*size, state_.hpack_table.max_bytes()));
|
966
|
+
(*dynamic_table_updates_allowed_)--;
|
967
|
+
grpc_error_handle err = table_->SetCurrentTableSize(*size);
|
968
|
+
if (!err.ok()) {
|
969
|
+
input_->SetErrorAndStopParsing(std::move(err));
|
1042
970
|
return false;
|
1043
971
|
}
|
1044
972
|
return true;
|
@@ -1047,13 +975,51 @@ class HPackParser::Parser {
|
|
1047
975
|
// Set an invalid hpack index error if no error has been set. Returns result
|
1048
976
|
// unmodified.
|
1049
977
|
void InvalidHPackIndexError(uint32_t index) {
|
1050
|
-
input_->SetErrorAndStopParsing(
|
1051
|
-
|
978
|
+
input_->SetErrorAndStopParsing(grpc_error_set_int(
|
979
|
+
grpc_error_set_int(absl::InternalError("Invalid HPACK index received"),
|
980
|
+
StatusIntProperty::kIndex,
|
981
|
+
static_cast<intptr_t>(index)),
|
982
|
+
StatusIntProperty::kSize,
|
983
|
+
static_cast<intptr_t>(this->table_->num_entries())));
|
984
|
+
}
|
985
|
+
|
986
|
+
GPR_ATTRIBUTE_NOINLINE
|
987
|
+
void HandleMetadataParseError(const absl::Status& status) {
|
988
|
+
if (metadata_buffer_ != nullptr) {
|
989
|
+
metadata_buffer_->Clear();
|
990
|
+
metadata_buffer_ = nullptr;
|
991
|
+
}
|
992
|
+
// StreamId is used as a signal to skip this stream but keep the connection
|
993
|
+
// alive
|
994
|
+
input_->SetErrorAndContinueParsing(status);
|
995
|
+
}
|
996
|
+
|
997
|
+
GPR_ATTRIBUTE_NOINLINE
|
998
|
+
void HandleMetadataHardSizeLimitExceeded(const HPackTable::Memento& md) {
|
999
|
+
// Collect a summary of sizes so far for debugging
|
1000
|
+
// Do not collect contents, for fear of exposing PII.
|
1001
|
+
std::string summary;
|
1002
|
+
std::string error_message;
|
1003
|
+
if (metadata_buffer_ != nullptr) {
|
1004
|
+
MetadataSizeLimitExceededEncoder encoder(summary);
|
1005
|
+
metadata_buffer_->Encode(&encoder);
|
1006
|
+
}
|
1007
|
+
summary = absl::StrCat("; adding ", md.md.key(), " (length ",
|
1008
|
+
md.md.transport_size(), "B)",
|
1009
|
+
summary.empty() ? "" : " to ", summary);
|
1010
|
+
error_message = absl::StrCat(
|
1011
|
+
"received metadata size exceeds hard limit (", *frame_length_, " vs. ",
|
1012
|
+
metadata_early_detection_->hard_limit(), ")", summary);
|
1013
|
+
HandleMetadataParseError(absl::ResourceExhaustedError(error_message));
|
1052
1014
|
}
|
1053
1015
|
|
1054
1016
|
Input* const input_;
|
1055
|
-
grpc_metadata_batch
|
1056
|
-
|
1017
|
+
grpc_metadata_batch* metadata_buffer_;
|
1018
|
+
HPackTable* const table_;
|
1019
|
+
uint8_t* const dynamic_table_updates_allowed_;
|
1020
|
+
uint32_t* const frame_length_;
|
1021
|
+
// Random early detection of metadata size limits.
|
1022
|
+
RandomEarlyDetection* metadata_early_detection_;
|
1057
1023
|
const LogInfo log_info_;
|
1058
1024
|
};
|
1059
1025
|
|
@@ -1085,8 +1051,9 @@ void HPackParser::BeginFrame(grpc_metadata_batch* metadata_buffer,
|
|
1085
1051
|
}
|
1086
1052
|
boundary_ = boundary;
|
1087
1053
|
priority_ = priority;
|
1088
|
-
|
1089
|
-
|
1054
|
+
dynamic_table_updates_allowed_ = 2;
|
1055
|
+
frame_length_ = 0;
|
1056
|
+
metadata_early_detection_ = RandomEarlyDetection(
|
1090
1057
|
/*soft_limit=*/metadata_size_soft_limit,
|
1091
1058
|
/*hard_limit=*/metadata_size_hard_limit);
|
1092
1059
|
log_info_ = log_info;
|
@@ -1094,43 +1061,36 @@ void HPackParser::BeginFrame(grpc_metadata_batch* metadata_buffer,
|
|
1094
1061
|
|
1095
1062
|
grpc_error_handle HPackParser::Parse(const grpc_slice& slice, bool is_last) {
|
1096
1063
|
if (GPR_UNLIKELY(!unparsed_bytes_.empty())) {
|
1097
|
-
unparsed_bytes_.insert(unparsed_bytes_.end(), GRPC_SLICE_START_PTR(slice),
|
1098
|
-
GRPC_SLICE_END_PTR(slice));
|
1099
|
-
if (!(is_last && is_boundary()) &&
|
1100
|
-
unparsed_bytes_.size() < min_progress_size_) {
|
1101
|
-
// We wouldn't make progress anyway, skip out.
|
1102
|
-
return absl::OkStatus();
|
1103
|
-
}
|
1104
1064
|
std::vector<uint8_t> buffer = std::move(unparsed_bytes_);
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1065
|
+
buffer.insert(buffer.end(), GRPC_SLICE_START_PTR(slice),
|
1066
|
+
GRPC_SLICE_END_PTR(slice));
|
1067
|
+
return ParseInput(
|
1068
|
+
Input(nullptr, buffer.data(), buffer.data() + buffer.size()), is_last);
|
1108
1069
|
}
|
1109
1070
|
return ParseInput(Input(slice.refcount, GRPC_SLICE_START_PTR(slice),
|
1110
|
-
GRPC_SLICE_END_PTR(slice)
|
1071
|
+
GRPC_SLICE_END_PTR(slice)),
|
1111
1072
|
is_last);
|
1112
1073
|
}
|
1113
1074
|
|
1114
1075
|
grpc_error_handle HPackParser::ParseInput(Input input, bool is_last) {
|
1115
1076
|
ParseInputInner(&input);
|
1116
|
-
if (is_last
|
1117
|
-
if (
|
1077
|
+
if (is_last) {
|
1078
|
+
if (metadata_early_detection_.Reject(frame_length_)) {
|
1118
1079
|
HandleMetadataSoftSizeLimitExceeded(&input);
|
1119
1080
|
}
|
1120
|
-
global_stats().IncrementHttp2MetadataSize(
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
if (input.eof_error() && !state_.frame_error.connection_error()) {
|
1129
|
-
unparsed_bytes_ = std::vector<uint8_t>(input.frontier(), input.end_ptr());
|
1130
|
-
min_progress_size_ = input.min_progress_size();
|
1081
|
+
global_stats().IncrementHttp2MetadataSize(frame_length_);
|
1082
|
+
}
|
1083
|
+
if (input.eof_error()) {
|
1084
|
+
if (GPR_UNLIKELY(is_last && is_boundary())) {
|
1085
|
+
auto err = input.TakeError();
|
1086
|
+
if (!err.ok() && !IsStreamError(err)) return err;
|
1087
|
+
return absl::InternalError(
|
1088
|
+
"Incomplete header at the end of a header/continuation sequence");
|
1131
1089
|
}
|
1132
|
-
|
1090
|
+
unparsed_bytes_ = std::vector<uint8_t>(input.frontier(), input.end_ptr());
|
1091
|
+
return input.TakeError();
|
1133
1092
|
}
|
1093
|
+
return input.TakeError();
|
1134
1094
|
}
|
1135
1095
|
|
1136
1096
|
void HPackParser::ParseInputInner(Input* input) {
|
@@ -1139,7 +1099,7 @@ void HPackParser::ParseInputInner(Input* input) {
|
|
1139
1099
|
break;
|
1140
1100
|
case Priority::Included: {
|
1141
1101
|
if (input->remaining() < 5) {
|
1142
|
-
input->UnexpectedEOF(
|
1102
|
+
input->UnexpectedEOF();
|
1143
1103
|
return;
|
1144
1104
|
}
|
1145
1105
|
input->Advance(5);
|
@@ -1148,8 +1108,10 @@ void HPackParser::ParseInputInner(Input* input) {
|
|
1148
1108
|
}
|
1149
1109
|
}
|
1150
1110
|
while (!input->end_of_stream()) {
|
1151
|
-
if (GPR_UNLIKELY(
|
1152
|
-
|
1111
|
+
if (GPR_UNLIKELY(!Parser(input, metadata_buffer_, &table_,
|
1112
|
+
&dynamic_table_updates_allowed_, &frame_length_,
|
1113
|
+
&metadata_early_detection_, log_info_)
|
1114
|
+
.Parse())) {
|
1153
1115
|
return;
|
1154
1116
|
}
|
1155
1117
|
input->UpdateFrontier();
|
@@ -1159,10 +1121,24 @@ void HPackParser::ParseInputInner(Input* input) {
|
|
1159
1121
|
void HPackParser::FinishFrame() { metadata_buffer_ = nullptr; }
|
1160
1122
|
|
1161
1123
|
void HPackParser::HandleMetadataSoftSizeLimitExceeded(Input* input) {
|
1124
|
+
// Collect a summary of sizes so far for debugging
|
1125
|
+
// Do not collect contents, for fear of exposing PII.
|
1126
|
+
std::string summary;
|
1127
|
+
std::string error_message;
|
1128
|
+
if (metadata_buffer_ != nullptr) {
|
1129
|
+
MetadataSizeLimitExceededEncoder encoder(summary);
|
1130
|
+
metadata_buffer_->Encode(&encoder);
|
1131
|
+
}
|
1132
|
+
error_message = absl::StrCat(
|
1133
|
+
"received metadata size exceeds soft limit (", frame_length_, " vs. ",
|
1134
|
+
metadata_early_detection_.soft_limit(),
|
1135
|
+
"), rejecting requests with some random probability", summary);
|
1136
|
+
if (metadata_buffer_ != nullptr) {
|
1137
|
+
metadata_buffer_->Clear();
|
1138
|
+
metadata_buffer_ = nullptr;
|
1139
|
+
}
|
1162
1140
|
input->SetErrorAndContinueParsing(
|
1163
|
-
|
1164
|
-
std::exchange(metadata_buffer_, nullptr), state_.frame_length,
|
1165
|
-
state_.metadata_early_detection.soft_limit()));
|
1141
|
+
absl::ResourceExhaustedError(error_message));
|
1166
1142
|
}
|
1167
1143
|
|
1168
1144
|
} // namespace grpc_core
|