[chaotic-good] Basic frame serialization/deserialization (#31257)

* [chaotic-good] initial sketch of frame serialization

* Automated change: Fix sanity tests

* tinkering

* fix up

* add tests,fuzzers

* more tests

* fix

* fuzzers

* Automated change: Fix sanity tests

* fix-build

* Automated change: Fix sanity tests

* fix inf loop

* fix refcounting bug

* fixdeps

* fix

* fix continuations

* iwyu

* fix build

* fix

* build fixes

* better split

* Automated change: Fix sanity tests

* Automated change: Fix sanity tests

* fixes

* iwyu

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/31629/head
Craig Tiller 2 years ago committed by GitHub
parent 1914a39875
commit 8185a56322
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 159
      BUILD
  2. 728
      CMakeLists.txt
  3. 2
      Makefile
  4. 507
      build_autogenerated.yaml
  5. 1
      config.m4
  6. 1
      config.w32
  7. 2
      gRPC-C++.podspec
  8. 3
      gRPC-Core.podspec
  9. 2
      grpc.gemspec
  10. 2
      grpc.gyp
  11. 2
      package.xml
  12. 49
      src/core/BUILD
  13. 307
      src/core/ext/transport/chaotic_good/frame.cc
  14. 122
      src/core/ext/transport/chaotic_good/frame.h
  15. 87
      src/core/ext/transport/chaotic_good/frame_header.cc
  16. 73
      src/core/ext/transport/chaotic_good/frame_header.h
  17. 2
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  18. 1
      src/core/ext/transport/chttp2/transport/chttp2_transport.h
  19. 2
      src/core/ext/transport/chttp2/transport/frame_rst_stream.cc
  20. 2
      src/core/ext/transport/chttp2/transport/frame_settings.cc
  21. 234
      src/core/ext/transport/chttp2/transport/hpack_encoder.cc
  22. 59
      src/core/ext/transport/chttp2/transport/hpack_encoder.h
  23. 72
      src/core/ext/transport/chttp2/transport/hpack_parser.cc
  24. 3
      src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
  25. 19
      src/core/ext/transport/chttp2/transport/http_trace.cc
  26. 24
      src/core/ext/transport/chttp2/transport/http_trace.h
  27. 1
      src/core/ext/transport/chttp2/transport/internal.h
  28. 67
      src/core/ext/transport/chttp2/transport/parsing.cc
  29. 2
      src/core/ext/transport/chttp2/transport/writing.cc
  30. 12
      src/core/lib/gprpp/bitset.h
  31. 3
      src/core/lib/iomgr/fork_posix.cc
  32. 4
      src/core/lib/slice/slice.h
  33. 7
      src/core/lib/slice/slice_buffer.cc
  34. 20
      src/core/lib/slice/slice_buffer.h
  35. 3
      src/core/lib/surface/init.cc
  36. 1
      src/core/lib/surface/init_internally.cc
  37. 1
      src/core/lib/surface/init_internally.h
  38. 1
      src/python/grpcio/grpc_core_dependencies.py
  39. 2
      templates/CMakeLists.txt.template
  40. 151
      test/core/promise/BUILD
  41. 78
      test/core/transport/chaotic_good/BUILD
  42. 112
      test/core/transport/chaotic_good/frame_fuzzer.cc
  43. BIN
      test/core/transport/chaotic_good/frame_fuzzer_corpus/crash-05c704327d21af2cc914de40e9d90d06f16ca0eb
  44. BIN
      test/core/transport/chaotic_good/frame_fuzzer_corpus/crash-5015de8c7cafb0b0ebbbfd28c29aedd5dbfdc03a
  45. BIN
      test/core/transport/chaotic_good/frame_fuzzer_corpus/crash-5a34978de8de6889ce913947a77f43f7cdea854c
  46. BIN
      test/core/transport/chaotic_good/frame_fuzzer_corpus/crash-608f798a51077a8cdc45b11f335c079a81339fbe
  47. BIN
      test/core/transport/chaotic_good/frame_fuzzer_corpus/crash-6a002cb46eac21af4ab6fd74b61ff3ce26d96dff
  48. BIN
      test/core/transport/chaotic_good/frame_fuzzer_corpus/crash-7732ddd35a4deb8b7c9e462aaf8680986755e540
  49. BIN
      test/core/transport/chaotic_good/frame_fuzzer_corpus/crash-c171e98ebfe8b6485f9a4bea0b9cdfe683776675
  50. 34
      test/core/transport/chaotic_good/frame_header_fuzzer.cc
  51. 1
      test/core/transport/chaotic_good/frame_header_fuzzer_corpus/0
  52. 120
      test/core/transport/chaotic_good/frame_header_test.cc
  53. 57
      test/core/transport/chaotic_good/frame_test.cc
  54. 2
      tools/distrib/fix_build_deps.py
  55. 2
      tools/doxygen/Doxyfile.c++.internal
  56. 2
      tools/doxygen/Doxyfile.core.internal
  57. 48
      tools/run_tests/generated/tests.json

159
BUILD

@ -479,7 +479,6 @@ grpc_cc_library(
language = "c++",
public_hdrs = GRPC_PUBLIC_HDRS,
tags = [
"avoid_dep",
"nofixdeps",
],
visibility = ["@grpc:public"],
@ -544,7 +543,6 @@ grpc_cc_library(
},
],
tags = [
"grpc_avoid_dep",
"nofixdeps",
],
visibility = [
@ -3297,11 +3295,144 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "chttp2_frame",
hdrs = [
"//src/core:ext/transport/chttp2/transport/frame.h",
],
deps = ["gpr"],
)
grpc_cc_library(
name = "http_trace",
srcs = [
"//src/core:ext/transport/chttp2/transport/http_trace.cc",
],
hdrs = [
"//src/core:ext/transport/chttp2/transport/http_trace.h",
],
deps = [
"gpr_platform",
"grpc_trace",
],
)
grpc_cc_library(
name = "hpack_parser_table",
srcs = [
"//src/core:ext/transport/chttp2/transport/hpack_parser_table.cc",
],
hdrs = [
"//src/core:ext/transport/chttp2/transport/hpack_parser_table.h",
],
external_deps = [
"absl/status",
"absl/strings",
"absl/strings:str_format",
],
deps = [
"gpr_public_hdrs",
"grpc_base",
"grpc_trace",
"http_trace",
"//src/core:error",
"//src/core:hpack_constants",
"//src/core:no_destruct",
"//src/core:slice",
],
)
grpc_cc_library(
name = "hpack_parser",
srcs = [
"//src/core:ext/transport/chttp2/transport/hpack_parser.cc",
],
hdrs = [
"//src/core:ext/transport/chttp2/transport/hpack_parser.h",
],
external_deps = [
"absl/base:core_headers",
"absl/status",
"absl/strings",
"absl/strings:str_format",
"absl/types:optional",
"absl/types:span",
"absl/types:variant",
],
deps = [
"chttp2_frame",
"gpr_public_hdrs",
"grpc_base",
"grpc_public_hdrs",
"grpc_trace",
"hpack_parser_table",
"//src/core:decode_huff",
"//src/core:error",
"//src/core:experiments",
"//src/core:hpack_constants",
"//src/core:slice",
"//src/core:slice_refcount",
"//src/core:status_helper",
],
)
grpc_cc_library(
name = "hpack_encoder",
srcs = [
"//src/core:ext/transport/chttp2/transport/hpack_encoder.cc",
],
hdrs = [
"//src/core:ext/transport/chttp2/transport/hpack_encoder.h",
],
external_deps = ["absl/strings"],
deps = [
"chttp2_bin_encoder",
"chttp2_frame",
"chttp2_varint",
"gpr_public_hdrs",
"grpc_base",
"grpc_public_hdrs",
"grpc_trace",
"http_trace",
"//src/core:hpack_constants",
"//src/core:hpack_encoder_table",
"//src/core:slice",
"//src/core:slice_buffer",
"//src/core:time",
],
)
grpc_cc_library(
name = "chttp2_bin_encoder",
srcs = [
"//src/core:ext/transport/chttp2/transport/bin_encoder.cc",
],
hdrs = [
"//src/core:ext/transport/chttp2/transport/bin_encoder.h",
],
deps = [
"gpr_public_hdrs",
"//src/core:huffsyms",
"//src/core:slice",
],
)
grpc_cc_library(
name = "chttp2_varint",
srcs = [
"//src/core:ext/transport/chttp2/transport/varint.cc",
],
hdrs = [
"//src/core:ext/transport/chttp2/transport/varint.h",
],
external_deps = ["absl/base:core_headers"],
deps = ["gpr_public_hdrs"],
)
grpc_cc_library(
name = "grpc_transport_chttp2",
srcs = [
"//src/core:ext/transport/chttp2/transport/bin_decoder.cc",
"//src/core:ext/transport/chttp2/transport/bin_encoder.cc",
"//src/core:ext/transport/chttp2/transport/chttp2_transport.cc",
"//src/core:ext/transport/chttp2/transport/context_list.cc",
"//src/core:ext/transport/chttp2/transport/frame_data.cc",
@ -3310,33 +3441,23 @@ grpc_cc_library(
"//src/core:ext/transport/chttp2/transport/frame_rst_stream.cc",
"//src/core:ext/transport/chttp2/transport/frame_settings.cc",
"//src/core:ext/transport/chttp2/transport/frame_window_update.cc",
"//src/core:ext/transport/chttp2/transport/hpack_encoder.cc",
"//src/core:ext/transport/chttp2/transport/hpack_parser.cc",
"//src/core:ext/transport/chttp2/transport/hpack_parser_table.cc",
"//src/core:ext/transport/chttp2/transport/parsing.cc",
"//src/core:ext/transport/chttp2/transport/stream_lists.cc",
"//src/core:ext/transport/chttp2/transport/stream_map.cc",
"//src/core:ext/transport/chttp2/transport/varint.cc",
"//src/core:ext/transport/chttp2/transport/writing.cc",
],
hdrs = [
"//src/core:ext/transport/chttp2/transport/bin_decoder.h",
"//src/core:ext/transport/chttp2/transport/bin_encoder.h",
"//src/core:ext/transport/chttp2/transport/chttp2_transport.h",
"//src/core:ext/transport/chttp2/transport/context_list.h",
"//src/core:ext/transport/chttp2/transport/frame.h",
"//src/core:ext/transport/chttp2/transport/frame_data.h",
"//src/core:ext/transport/chttp2/transport/frame_goaway.h",
"//src/core:ext/transport/chttp2/transport/frame_ping.h",
"//src/core:ext/transport/chttp2/transport/frame_rst_stream.h",
"//src/core:ext/transport/chttp2/transport/frame_settings.h",
"//src/core:ext/transport/chttp2/transport/frame_window_update.h",
"//src/core:ext/transport/chttp2/transport/hpack_encoder.h",
"//src/core:ext/transport/chttp2/transport/hpack_parser.h",
"//src/core:ext/transport/chttp2/transport/hpack_parser_table.h",
"//src/core:ext/transport/chttp2/transport/internal.h",
"//src/core:ext/transport/chttp2/transport/stream_map.h",
"//src/core:ext/transport/chttp2/transport/varint.h",
],
external_deps = [
"absl/base:core_headers",
@ -3345,17 +3466,22 @@ grpc_cc_library(
"absl/strings:cord",
"absl/strings:str_format",
"absl/types:optional",
"absl/types:span",
"absl/types:variant",
],
language = "c++",
visibility = ["@grpc:grpclb"],
deps = [
"chttp2_frame",
"chttp2_varint",
"debug_location",
"gpr",
"grpc_base",
"grpc_public_hdrs",
"grpc_trace",
"hpack_encoder",
"hpack_parser",
"hpack_parser_table",
"http_trace",
"httpcli",
"iomgr_timer",
"ref_counted_ptr",
@ -3364,19 +3490,14 @@ grpc_cc_library(
"//src/core:bdp_estimator",
"//src/core:bitset",
"//src/core:chttp2_flow_control",
"//src/core:decode_huff",
"//src/core:error",
"//src/core:experiments",
"//src/core:gpr_atm",
"//src/core:hpack_constants",
"//src/core:hpack_encoder_table",
"//src/core:http2_errors",
"//src/core:http2_settings",
"//src/core:huffsyms",
"//src/core:init_internally",
"//src/core:iomgr_fwd",
"//src/core:memory_quota",
"//src/core:no_destruct",
"//src/core:poll",
"//src/core:ref_counted",
"//src/core:resource_quota",

728
CMakeLists.txt generated

File diff suppressed because it is too large Load Diff

2
Makefile generated

@ -1051,6 +1051,7 @@ LIBGRPC_SRC = \
src/core/ext/transport/chttp2/transport/hpack_parser.cc \
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
src/core/ext/transport/chttp2/transport/http2_settings.cc \
src/core/ext/transport/chttp2/transport/http_trace.cc \
src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/parsing.cc \
src/core/ext/transport/chttp2/transport/stream_lists.cc \
@ -1858,6 +1859,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/transport/chttp2/transport/hpack_parser.cc \
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
src/core/ext/transport/chttp2/transport/http2_settings.cc \
src/core/ext/transport/chttp2/transport/http_trace.cc \
src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/parsing.cc \
src/core/ext/transport/chttp2/transport/stream_lists.cc \

@ -399,6 +399,7 @@ libs:
- src/core/ext/transport/chttp2/transport/hpack_parser.h
- src/core/ext/transport/chttp2/transport/hpack_parser_table.h
- src/core/ext/transport/chttp2/transport/http2_settings.h
- src/core/ext/transport/chttp2/transport/http_trace.h
- src/core/ext/transport/chttp2/transport/huffsyms.h
- src/core/ext/transport/chttp2/transport/internal.h
- src/core/ext/transport/chttp2/transport/stream_map.h
@ -1139,6 +1140,7 @@ libs:
- src/core/ext/transport/chttp2/transport/hpack_parser.cc
- src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
- src/core/ext/transport/chttp2/transport/http2_settings.cc
- src/core/ext/transport/chttp2/transport/http_trace.cc
- src/core/ext/transport/chttp2/transport/huffsyms.cc
- src/core/ext/transport/chttp2/transport/parsing.cc
- src/core/ext/transport/chttp2/transport/stream_lists.cc
@ -1960,6 +1962,7 @@ libs:
- src/core/ext/transport/chttp2/transport/hpack_parser.h
- src/core/ext/transport/chttp2/transport/hpack_parser_table.h
- src/core/ext/transport/chttp2/transport/http2_settings.h
- src/core/ext/transport/chttp2/transport/http_trace.h
- src/core/ext/transport/chttp2/transport/huffsyms.h
- src/core/ext/transport/chttp2/transport/internal.h
- src/core/ext/transport/chttp2/transport/stream_map.h
@ -2341,6 +2344,7 @@ libs:
- src/core/ext/transport/chttp2/transport/hpack_parser.cc
- src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
- src/core/ext/transport/chttp2/transport/http2_settings.cc
- src/core/ext/transport/chttp2/transport/http_trace.cc
- src/core/ext/transport/chttp2/transport/huffsyms.cc
- src/core/ext/transport/chttp2/transport/parsing.cc
- src/core/ext/transport/chttp2/transport/stream_lists.cc
@ -6448,13 +6452,11 @@ targets:
- src/core/lib/promise/join.h
- src/core/lib/promise/loop.h
- src/core/lib/promise/map.h
- src/core/lib/promise/observable.h
- src/core/lib/promise/pipe.h
- src/core/lib/promise/poll.h
- src/core/lib/promise/race.h
- src/core/lib/promise/seq.h
- src/core/lib/promise/try_seq.h
- src/core/lib/promise/wait_set.h
- src/core/lib/resource_quota/arena.h
- src/core/lib/resource_quota/memory_quota.h
- src/core/lib/resource_quota/periodic_update.h
@ -6494,7 +6496,6 @@ targets:
- src/core/lib/slice/slice_string_helpers.cc
- test/core/promise/for_each_test.cc
deps:
- absl/container:flat_hash_set
- absl/functional:any_invocable
- absl/functional:function_ref
- absl/hash:hash
@ -6582,6 +6583,502 @@ targets:
- test/core/tsi/alts/frame_protector/frame_handler_test.cc
deps:
- grpc_test_util
- name: frame_header_test
gtest: true
build: test
language: c++
headers:
- src/core/ext/transport/chaotic_good/frame_header.h
- src/core/lib/gpr/useful.h
- src/core/lib/gprpp/bitset.h
src:
- src/core/ext/transport/chaotic_good/frame_header.cc
- test/core/transport/chaotic_good/frame_header_test.cc
deps:
- absl/status:status
- absl/status:statusor
- absl/strings:strings
- absl/types:variant
- name: frame_test
gtest: true
build: test
language: c++
headers:
- src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h
- src/core/ext/transport/chaotic_good/frame.h
- src/core/ext/transport/chaotic_good/frame_header.h
- src/core/ext/transport/chttp2/transport/bin_encoder.h
- src/core/ext/transport/chttp2/transport/decode_huff.h
- src/core/ext/transport/chttp2/transport/frame.h
- src/core/ext/transport/chttp2/transport/hpack_constants.h
- src/core/ext/transport/chttp2/transport/hpack_encoder.h
- src/core/ext/transport/chttp2/transport/hpack_encoder_table.h
- src/core/ext/transport/chttp2/transport/hpack_parser.h
- src/core/ext/transport/chttp2/transport/hpack_parser_table.h
- src/core/ext/transport/chttp2/transport/http_trace.h
- src/core/ext/transport/chttp2/transport/huffsyms.h
- src/core/ext/transport/chttp2/transport/varint.h
- src/core/ext/upb-generated/google/protobuf/any.upb.h
- src/core/ext/upb-generated/google/rpc/status.upb.h
- src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h
- src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h
- src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h
- src/core/lib/address_utils/parse_address.h
- src/core/lib/address_utils/sockaddr_utils.h
- src/core/lib/avl/avl.h
- src/core/lib/channel/call_finalization.h
- src/core/lib/channel/call_tracer.h
- src/core/lib/channel/channel_args.h
- src/core/lib/channel/channel_args_preconditioning.h
- src/core/lib/channel/channel_fwd.h
- src/core/lib/channel/channel_stack.h
- src/core/lib/channel/channel_stack_builder.h
- src/core/lib/channel/channel_stack_builder_impl.h
- src/core/lib/channel/channel_trace.h
- src/core/lib/channel/channelz.h
- src/core/lib/channel/channelz_registry.h
- src/core/lib/channel/connected_channel.h
- src/core/lib/channel/context.h
- src/core/lib/channel/promise_based_filter.h
- src/core/lib/channel/status_util.h
- src/core/lib/compression/compression_internal.h
- src/core/lib/compression/message_compress.h
- src/core/lib/config/core_configuration.h
- src/core/lib/debug/event_log.h
- src/core/lib/debug/histogram_view.h
- src/core/lib/debug/stats.h
- src/core/lib/debug/stats_data.h
- src/core/lib/debug/trace.h
- src/core/lib/event_engine/channel_args_endpoint_config.h
- src/core/lib/event_engine/common_closures.h
- src/core/lib/event_engine/default_event_engine.h
- src/core/lib/event_engine/default_event_engine_factory.h
- src/core/lib/event_engine/executor/executor.h
- src/core/lib/event_engine/forkable.h
- src/core/lib/event_engine/handle_containers.h
- src/core/lib/event_engine/poller.h
- src/core/lib/event_engine/posix_engine/ev_epoll1_linux.h
- src/core/lib/event_engine/posix_engine/ev_poll_posix.h
- src/core/lib/event_engine/posix_engine/event_poller.h
- src/core/lib/event_engine/posix_engine/event_poller_posix_default.h
- src/core/lib/event_engine/posix_engine/internal_errqueue.h
- src/core/lib/event_engine/posix_engine/lockfree_event.h
- src/core/lib/event_engine/posix_engine/posix_endpoint.h
- src/core/lib/event_engine/posix_engine/posix_engine.h
- src/core/lib/event_engine/posix_engine/posix_engine_closure.h
- src/core/lib/event_engine/posix_engine/tcp_socket_utils.h
- src/core/lib/event_engine/posix_engine/timer.h
- src/core/lib/event_engine/posix_engine/timer_heap.h
- src/core/lib/event_engine/posix_engine/timer_manager.h
- src/core/lib/event_engine/posix_engine/traced_buffer_list.h
- src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.h
- src/core/lib/event_engine/posix_engine/wakeup_fd_pipe.h
- src/core/lib/event_engine/posix_engine/wakeup_fd_posix.h
- src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.h
- src/core/lib/event_engine/socket_notifier.h
- src/core/lib/event_engine/thread_pool.h
- src/core/lib/event_engine/time_util.h
- src/core/lib/event_engine/trace.h
- src/core/lib/event_engine/utils.h
- src/core/lib/event_engine/windows/iocp.h
- src/core/lib/event_engine/windows/win_socket.h
- src/core/lib/event_engine/windows/windows_engine.h
- src/core/lib/experiments/config.h
- src/core/lib/experiments/experiments.h
- src/core/lib/gpr/spinlock.h
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/bitset.h
- src/core/lib/gprpp/chunked_vector.h
- src/core/lib/gprpp/cpp_impl_of.h
- src/core/lib/gprpp/debug_location.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/load_file.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/match.h
- src/core/lib/gprpp/notification.h
- src/core/lib/gprpp/orphanable.h
- src/core/lib/gprpp/overload.h
- src/core/lib/gprpp/packed_table.h
- src/core/lib/gprpp/per_cpu.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/gprpp/sorted_pack.h
- src/core/lib/gprpp/status_helper.h
- src/core/lib/gprpp/table.h
- src/core/lib/gprpp/time.h
- src/core/lib/gprpp/time_averaged_stats.h
- src/core/lib/gprpp/unique_type_name.h
- src/core/lib/gprpp/validation_errors.h
- src/core/lib/gprpp/work_serializer.h
- src/core/lib/handshaker/proxy_mapper.h
- src/core/lib/handshaker/proxy_mapper_registry.h
- src/core/lib/iomgr/block_annotate.h
- src/core/lib/iomgr/buffer_list.h
- src/core/lib/iomgr/call_combiner.h
- src/core/lib/iomgr/cfstream_handle.h
- src/core/lib/iomgr/closure.h
- src/core/lib/iomgr/combiner.h
- src/core/lib/iomgr/dynamic_annotations.h
- src/core/lib/iomgr/endpoint.h
- src/core/lib/iomgr/endpoint_cfstream.h
- src/core/lib/iomgr/endpoint_pair.h
- src/core/lib/iomgr/error.h
- src/core/lib/iomgr/error_cfstream.h
- src/core/lib/iomgr/ev_apple.h
- src/core/lib/iomgr/ev_epoll1_linux.h
- src/core/lib/iomgr/ev_poll_posix.h
- src/core/lib/iomgr/ev_posix.h
- src/core/lib/iomgr/exec_ctx.h
- src/core/lib/iomgr/executor.h
- src/core/lib/iomgr/gethostname.h
- src/core/lib/iomgr/grpc_if_nametoindex.h
- src/core/lib/iomgr/internal_errqueue.h
- src/core/lib/iomgr/iocp_windows.h
- src/core/lib/iomgr/iomgr.h
- src/core/lib/iomgr/iomgr_fwd.h
- src/core/lib/iomgr/iomgr_internal.h
- src/core/lib/iomgr/load_file.h
- src/core/lib/iomgr/lockfree_event.h
- src/core/lib/iomgr/nameser.h
- src/core/lib/iomgr/polling_entity.h
- src/core/lib/iomgr/pollset.h
- src/core/lib/iomgr/pollset_set.h
- src/core/lib/iomgr/pollset_set_windows.h
- src/core/lib/iomgr/pollset_windows.h
- src/core/lib/iomgr/port.h
- src/core/lib/iomgr/python_util.h
- src/core/lib/iomgr/resolve_address.h
- src/core/lib/iomgr/resolve_address_impl.h
- src/core/lib/iomgr/resolve_address_posix.h
- src/core/lib/iomgr/resolve_address_windows.h
- src/core/lib/iomgr/resolved_address.h
- src/core/lib/iomgr/sockaddr.h
- src/core/lib/iomgr/sockaddr_posix.h
- src/core/lib/iomgr/sockaddr_windows.h
- src/core/lib/iomgr/socket_factory_posix.h
- src/core/lib/iomgr/socket_mutator.h
- src/core/lib/iomgr/socket_utils.h
- src/core/lib/iomgr/socket_utils_posix.h
- src/core/lib/iomgr/socket_windows.h
- src/core/lib/iomgr/tcp_client.h
- src/core/lib/iomgr/tcp_client_posix.h
- src/core/lib/iomgr/tcp_posix.h
- src/core/lib/iomgr/tcp_server.h
- src/core/lib/iomgr/tcp_server_utils_posix.h
- src/core/lib/iomgr/tcp_windows.h
- src/core/lib/iomgr/timer.h
- src/core/lib/iomgr/timer_generic.h
- src/core/lib/iomgr/timer_heap.h
- src/core/lib/iomgr/timer_manager.h
- src/core/lib/iomgr/unix_sockets_posix.h
- src/core/lib/iomgr/wakeup_fd_pipe.h
- src/core/lib/iomgr/wakeup_fd_posix.h
- src/core/lib/json/json.h
- src/core/lib/load_balancing/lb_policy.h
- src/core/lib/load_balancing/lb_policy_factory.h
- src/core/lib/load_balancing/lb_policy_registry.h
- src/core/lib/load_balancing/subchannel_interface.h
- src/core/lib/promise/activity.h
- src/core/lib/promise/arena_promise.h
- src/core/lib/promise/context.h
- src/core/lib/promise/detail/basic_seq.h
- src/core/lib/promise/detail/promise_factory.h
- src/core/lib/promise/detail/promise_like.h
- src/core/lib/promise/detail/status.h
- src/core/lib/promise/detail/switch.h
- src/core/lib/promise/exec_ctx_wakeup_scheduler.h
- src/core/lib/promise/intra_activity_waiter.h
- src/core/lib/promise/latch.h
- src/core/lib/promise/loop.h
- src/core/lib/promise/map.h
- src/core/lib/promise/pipe.h
- src/core/lib/promise/poll.h
- src/core/lib/promise/promise.h
- src/core/lib/promise/race.h
- src/core/lib/promise/seq.h
- src/core/lib/resolver/resolver.h
- src/core/lib/resolver/resolver_factory.h
- src/core/lib/resolver/resolver_registry.h
- src/core/lib/resolver/server_address.h
- src/core/lib/resource_quota/api.h
- src/core/lib/resource_quota/arena.h
- src/core/lib/resource_quota/memory_quota.h
- src/core/lib/resource_quota/periodic_update.h
- src/core/lib/resource_quota/resource_quota.h
- src/core/lib/resource_quota/thread_quota.h
- src/core/lib/resource_quota/trace.h
- src/core/lib/security/certificate_provider/certificate_provider_factory.h
- src/core/lib/security/certificate_provider/certificate_provider_registry.h
- src/core/lib/security/credentials/alts/check_gcp_environment.h
- src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
- src/core/lib/security/credentials/channel_creds_registry.h
- src/core/lib/service_config/service_config.h
- src/core/lib/service_config/service_config_call_data.h
- src/core/lib/service_config/service_config_parser.h
- src/core/lib/slice/b64.h
- src/core/lib/slice/percent_encoding.h
- src/core/lib/slice/slice.h
- src/core/lib/slice/slice_buffer.h
- src/core/lib/slice/slice_internal.h
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/lib/surface/api_trace.h
- src/core/lib/surface/builtins.h
- src/core/lib/surface/call.h
- src/core/lib/surface/call_test_only.h
- src/core/lib/surface/call_trace.h
- src/core/lib/surface/channel.h
- src/core/lib/surface/channel_init.h
- src/core/lib/surface/channel_stack_type.h
- src/core/lib/surface/completion_queue.h
- src/core/lib/surface/completion_queue_factory.h
- src/core/lib/surface/event_string.h
- src/core/lib/surface/init.h
- src/core/lib/surface/init_internally.h
- src/core/lib/surface/lame_client.h
- src/core/lib/surface/server.h
- src/core/lib/surface/validate_metadata.h
- src/core/lib/transport/connectivity_state.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/handshaker_factory.h
- src/core/lib/transport/handshaker_registry.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/metadata_batch.h
- src/core/lib/transport/parsed_metadata.h
- src/core/lib/transport/status_conversion.h
- src/core/lib/transport/timeout_encoding.h
- src/core/lib/transport/transport.h
- src/core/lib/transport/transport_fwd.h
- src/core/lib/transport/transport_impl.h
- src/core/lib/uri/uri_parser.h
- src/core/tsi/alts/handshaker/transport_security_common_api.h
src:
- src/core/ext/transport/chaotic_good/frame.cc
- src/core/ext/transport/chaotic_good/frame_header.cc
- src/core/ext/transport/chttp2/transport/bin_encoder.cc
- src/core/ext/transport/chttp2/transport/decode_huff.cc
- src/core/ext/transport/chttp2/transport/hpack_encoder.cc
- src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc
- src/core/ext/transport/chttp2/transport/hpack_parser.cc
- src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
- src/core/ext/transport/chttp2/transport/http_trace.cc
- src/core/ext/transport/chttp2/transport/huffsyms.cc
- src/core/ext/transport/chttp2/transport/varint.cc
- src/core/ext/upb-generated/google/protobuf/any.upb.c
- src/core/ext/upb-generated/google/rpc/status.upb.c
- src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c
- src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c
- src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c
- src/core/lib/address_utils/parse_address.cc
- src/core/lib/address_utils/sockaddr_utils.cc
- src/core/lib/channel/channel_args.cc
- src/core/lib/channel/channel_args_preconditioning.cc
- src/core/lib/channel/channel_stack.cc
- src/core/lib/channel/channel_stack_builder.cc
- src/core/lib/channel/channel_stack_builder_impl.cc
- src/core/lib/channel/channel_trace.cc
- src/core/lib/channel/channelz.cc
- src/core/lib/channel/channelz_registry.cc
- src/core/lib/channel/connected_channel.cc
- src/core/lib/channel/promise_based_filter.cc
- src/core/lib/channel/status_util.cc
- src/core/lib/compression/compression.cc
- src/core/lib/compression/compression_internal.cc
- src/core/lib/compression/message_compress.cc
- src/core/lib/config/core_configuration.cc
- src/core/lib/debug/event_log.cc
- src/core/lib/debug/histogram_view.cc
- src/core/lib/debug/stats.cc
- src/core/lib/debug/stats_data.cc
- src/core/lib/debug/trace.cc
- src/core/lib/event_engine/channel_args_endpoint_config.cc
- src/core/lib/event_engine/default_event_engine.cc
- src/core/lib/event_engine/default_event_engine_factory.cc
- src/core/lib/event_engine/forkable.cc
- src/core/lib/event_engine/memory_allocator.cc
- src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc
- src/core/lib/event_engine/posix_engine/ev_poll_posix.cc
- src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc
- src/core/lib/event_engine/posix_engine/internal_errqueue.cc
- src/core/lib/event_engine/posix_engine/lockfree_event.cc
- src/core/lib/event_engine/posix_engine/posix_endpoint.cc
- src/core/lib/event_engine/posix_engine/posix_engine.cc
- src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc
- src/core/lib/event_engine/posix_engine/timer.cc
- src/core/lib/event_engine/posix_engine/timer_heap.cc
- src/core/lib/event_engine/posix_engine/timer_manager.cc
- src/core/lib/event_engine/posix_engine/traced_buffer_list.cc
- src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.cc
- src/core/lib/event_engine/posix_engine/wakeup_fd_pipe.cc
- src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.cc
- src/core/lib/event_engine/resolved_address.cc
- src/core/lib/event_engine/slice.cc
- src/core/lib/event_engine/slice_buffer.cc
- src/core/lib/event_engine/thread_pool.cc
- src/core/lib/event_engine/time_util.cc
- src/core/lib/event_engine/trace.cc
- src/core/lib/event_engine/utils.cc
- src/core/lib/event_engine/windows/iocp.cc
- src/core/lib/event_engine/windows/win_socket.cc
- src/core/lib/event_engine/windows/windows_engine.cc
- src/core/lib/experiments/config.cc
- src/core/lib/experiments/experiments.cc
- src/core/lib/gprpp/load_file.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/gprpp/time_averaged_stats.cc
- src/core/lib/gprpp/validation_errors.cc
- src/core/lib/gprpp/work_serializer.cc
- src/core/lib/handshaker/proxy_mapper_registry.cc
- src/core/lib/iomgr/buffer_list.cc
- src/core/lib/iomgr/call_combiner.cc
- src/core/lib/iomgr/cfstream_handle.cc
- src/core/lib/iomgr/combiner.cc
- src/core/lib/iomgr/dualstack_socket_posix.cc
- src/core/lib/iomgr/endpoint.cc
- src/core/lib/iomgr/endpoint_cfstream.cc
- src/core/lib/iomgr/endpoint_pair_posix.cc
- src/core/lib/iomgr/endpoint_pair_windows.cc
- src/core/lib/iomgr/error.cc
- src/core/lib/iomgr/error_cfstream.cc
- src/core/lib/iomgr/ev_apple.cc
- src/core/lib/iomgr/ev_epoll1_linux.cc
- src/core/lib/iomgr/ev_poll_posix.cc
- src/core/lib/iomgr/ev_posix.cc
- src/core/lib/iomgr/ev_windows.cc
- src/core/lib/iomgr/exec_ctx.cc
- src/core/lib/iomgr/executor.cc
- src/core/lib/iomgr/fork_posix.cc
- src/core/lib/iomgr/fork_windows.cc
- src/core/lib/iomgr/gethostname_fallback.cc
- src/core/lib/iomgr/gethostname_host_name_max.cc
- src/core/lib/iomgr/gethostname_sysconf.cc
- src/core/lib/iomgr/grpc_if_nametoindex_posix.cc
- src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc
- src/core/lib/iomgr/internal_errqueue.cc
- src/core/lib/iomgr/iocp_windows.cc
- src/core/lib/iomgr/iomgr.cc
- src/core/lib/iomgr/iomgr_internal.cc
- src/core/lib/iomgr/iomgr_posix.cc
- src/core/lib/iomgr/iomgr_posix_cfstream.cc
- src/core/lib/iomgr/iomgr_windows.cc
- src/core/lib/iomgr/load_file.cc
- src/core/lib/iomgr/lockfree_event.cc
- src/core/lib/iomgr/polling_entity.cc
- src/core/lib/iomgr/pollset.cc
- src/core/lib/iomgr/pollset_set.cc
- src/core/lib/iomgr/pollset_set_windows.cc
- src/core/lib/iomgr/pollset_windows.cc
- src/core/lib/iomgr/resolve_address.cc
- src/core/lib/iomgr/resolve_address_posix.cc
- src/core/lib/iomgr/resolve_address_windows.cc
- src/core/lib/iomgr/sockaddr_utils_posix.cc
- src/core/lib/iomgr/socket_factory_posix.cc
- src/core/lib/iomgr/socket_mutator.cc
- src/core/lib/iomgr/socket_utils_common_posix.cc
- src/core/lib/iomgr/socket_utils_linux.cc
- src/core/lib/iomgr/socket_utils_posix.cc
- src/core/lib/iomgr/socket_utils_windows.cc
- src/core/lib/iomgr/socket_windows.cc
- src/core/lib/iomgr/tcp_client.cc
- src/core/lib/iomgr/tcp_client_cfstream.cc
- src/core/lib/iomgr/tcp_client_posix.cc
- src/core/lib/iomgr/tcp_client_windows.cc
- src/core/lib/iomgr/tcp_posix.cc
- src/core/lib/iomgr/tcp_server.cc
- src/core/lib/iomgr/tcp_server_posix.cc
- src/core/lib/iomgr/tcp_server_utils_posix_common.cc
- src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc
- src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc
- src/core/lib/iomgr/tcp_server_windows.cc
- src/core/lib/iomgr/tcp_windows.cc
- src/core/lib/iomgr/timer.cc
- src/core/lib/iomgr/timer_generic.cc
- src/core/lib/iomgr/timer_heap.cc
- src/core/lib/iomgr/timer_manager.cc
- src/core/lib/iomgr/unix_sockets_posix.cc
- src/core/lib/iomgr/unix_sockets_posix_noop.cc
- src/core/lib/iomgr/wakeup_fd_eventfd.cc
- src/core/lib/iomgr/wakeup_fd_nospecial.cc
- src/core/lib/iomgr/wakeup_fd_pipe.cc
- src/core/lib/iomgr/wakeup_fd_posix.cc
- src/core/lib/json/json_reader.cc
- src/core/lib/json/json_writer.cc
- src/core/lib/load_balancing/lb_policy.cc
- src/core/lib/load_balancing/lb_policy_registry.cc
- src/core/lib/promise/activity.cc
- src/core/lib/promise/pipe.cc
- src/core/lib/resolver/resolver.cc
- src/core/lib/resolver/resolver_registry.cc
- src/core/lib/resolver/server_address.cc
- src/core/lib/resource_quota/api.cc
- src/core/lib/resource_quota/arena.cc
- src/core/lib/resource_quota/memory_quota.cc
- src/core/lib/resource_quota/periodic_update.cc
- src/core/lib/resource_quota/resource_quota.cc
- src/core/lib/resource_quota/thread_quota.cc
- src/core/lib/resource_quota/trace.cc
- src/core/lib/security/certificate_provider/certificate_provider_registry.cc
- src/core/lib/security/credentials/alts/check_gcp_environment.cc
- src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc
- src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc
- src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc
- src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
- src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc
- src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc
- src/core/lib/service_config/service_config_parser.cc
- src/core/lib/slice/b64.cc
- src/core/lib/slice/percent_encoding.cc
- src/core/lib/slice/slice.cc
- src/core/lib/slice/slice_buffer.cc
- src/core/lib/slice/slice_string_helpers.cc
- src/core/lib/surface/api_trace.cc
- src/core/lib/surface/builtins.cc
- src/core/lib/surface/byte_buffer.cc
- src/core/lib/surface/byte_buffer_reader.cc
- src/core/lib/surface/call.cc
- src/core/lib/surface/call_details.cc
- src/core/lib/surface/call_log_batch.cc
- src/core/lib/surface/call_trace.cc
- src/core/lib/surface/channel.cc
- src/core/lib/surface/channel_init.cc
- src/core/lib/surface/channel_ping.cc
- src/core/lib/surface/channel_stack_type.cc
- src/core/lib/surface/completion_queue.cc
- src/core/lib/surface/completion_queue_factory.cc
- src/core/lib/surface/event_string.cc
- src/core/lib/surface/init_internally.cc
- src/core/lib/surface/lame_client.cc
- src/core/lib/surface/metadata_array.cc
- src/core/lib/surface/server.cc
- src/core/lib/surface/validate_metadata.cc
- src/core/lib/surface/version.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/handshaker_registry.cc
- src/core/lib/transport/metadata_batch.cc
- src/core/lib/transport/parsed_metadata.cc
- src/core/lib/transport/status_conversion.cc
- src/core/lib/transport/timeout_encoding.cc
- src/core/lib/transport/transport.cc
- src/core/lib/transport/transport_op_string.cc
- src/core/lib/uri/uri_parser.cc
- src/core/tsi/alts/handshaker/transport_security_common_api.cc
- test/core/transport/chaotic_good/frame_test.cc
deps:
- absl/cleanup:cleanup
- absl/container:flat_hash_map
- absl/container:flat_hash_set
- absl/container:inlined_vector
- absl/functional:any_invocable
- absl/functional:function_ref
- absl/hash:hash
- absl/meta:type_traits
- absl/status:statusor
- absl/types:span
- absl/utility:utility
- gpr
- upb
- name: fuzzing_event_engine_test
gtest: true
build: test
@ -7895,13 +8392,11 @@ targets:
- src/core/lib/promise/loop.h
- src/core/lib/promise/map.h
- src/core/lib/promise/map_pipe.h
- src/core/lib/promise/observable.h
- src/core/lib/promise/pipe.h
- src/core/lib/promise/poll.h
- src/core/lib/promise/race.h
- src/core/lib/promise/seq.h
- src/core/lib/promise/try_seq.h
- src/core/lib/promise/wait_set.h
- src/core/lib/resource_quota/arena.h
- src/core/lib/resource_quota/memory_quota.h
- src/core/lib/resource_quota/periodic_update.h
@ -7941,7 +8436,6 @@ targets:
- src/core/lib/slice/slice_string_helpers.cc
- test/core/promise/map_pipe_test.cc
deps:
- absl/container:flat_hash_set
- absl/functional:any_invocable
- absl/functional:function_ref
- absl/hash:hash
@ -8548,7 +9042,6 @@ targets:
- src/core/lib/promise/map.h
- src/core/lib/promise/pipe.h
- src/core/lib/promise/poll.h
- src/core/lib/promise/promise.h
- src/core/lib/promise/race.h
- src/core/lib/promise/seq.h
- src/core/lib/resource_quota/arena.h

1
config.m4 generated

@ -133,6 +133,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/transport/chttp2/transport/hpack_parser.cc \
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
src/core/ext/transport/chttp2/transport/http2_settings.cc \
src/core/ext/transport/chttp2/transport/http_trace.cc \
src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/parsing.cc \
src/core/ext/transport/chttp2/transport/stream_lists.cc \

1
config.w32 generated

@ -99,6 +99,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\transport\\chttp2\\transport\\hpack_parser.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\hpack_parser_table.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\http2_settings.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\http_trace.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\huffsyms.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\parsing.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\stream_lists.cc " +

2
gRPC-C++.podspec generated

@ -343,6 +343,7 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/hpack_parser.h',
'src/core/ext/transport/chttp2/transport/hpack_parser_table.h',
'src/core/ext/transport/chttp2/transport/http2_settings.h',
'src/core/ext/transport/chttp2/transport/http_trace.h',
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/stream_map.h',
@ -1227,6 +1228,7 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/hpack_parser.h',
'src/core/ext/transport/chttp2/transport/hpack_parser_table.h',
'src/core/ext/transport/chttp2/transport/http2_settings.h',
'src/core/ext/transport/chttp2/transport/http_trace.h',
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/stream_map.h',

3
gRPC-Core.podspec generated

@ -369,6 +369,8 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/hpack_parser_table.h',
'src/core/ext/transport/chttp2/transport/http2_settings.cc',
'src/core/ext/transport/chttp2/transport/http2_settings.h',
'src/core/ext/transport/chttp2/transport/http_trace.cc',
'src/core/ext/transport/chttp2/transport/http_trace.h',
'src/core/ext/transport/chttp2/transport/huffsyms.cc',
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
@ -1865,6 +1867,7 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/hpack_parser.h',
'src/core/ext/transport/chttp2/transport/hpack_parser_table.h',
'src/core/ext/transport/chttp2/transport/http2_settings.h',
'src/core/ext/transport/chttp2/transport/http_trace.h',
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/stream_map.h',

2
grpc.gemspec generated

@ -280,6 +280,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser_table.h )
s.files += %w( src/core/ext/transport/chttp2/transport/http2_settings.cc )
s.files += %w( src/core/ext/transport/chttp2/transport/http2_settings.h )
s.files += %w( src/core/ext/transport/chttp2/transport/http_trace.cc )
s.files += %w( src/core/ext/transport/chttp2/transport/http_trace.h )
s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.cc )
s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )

2
grpc.gyp generated

@ -465,6 +465,7 @@
'src/core/ext/transport/chttp2/transport/hpack_parser.cc',
'src/core/ext/transport/chttp2/transport/hpack_parser_table.cc',
'src/core/ext/transport/chttp2/transport/http2_settings.cc',
'src/core/ext/transport/chttp2/transport/http_trace.cc',
'src/core/ext/transport/chttp2/transport/huffsyms.cc',
'src/core/ext/transport/chttp2/transport/parsing.cc',
'src/core/ext/transport/chttp2/transport/stream_lists.cc',
@ -1219,6 +1220,7 @@
'src/core/ext/transport/chttp2/transport/hpack_parser.cc',
'src/core/ext/transport/chttp2/transport/hpack_parser_table.cc',
'src/core/ext/transport/chttp2/transport/http2_settings.cc',
'src/core/ext/transport/chttp2/transport/http_trace.cc',
'src/core/ext/transport/chttp2/transport/huffsyms.cc',
'src/core/ext/transport/chttp2/transport/parsing.cc',
'src/core/ext/transport/chttp2/transport/stream_lists.cc',

2
package.xml generated

@ -262,6 +262,8 @@
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser_table.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_settings.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_settings.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http_trace.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http_trace.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />

@ -4623,6 +4623,7 @@ grpc_cc_library(
"time",
"transport_fwd",
"unique_type_name",
"//:chttp2_frame",
"//:config",
"//:debug_location",
"//:gpr",
@ -4676,6 +4677,54 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "chaotic_good_frame",
srcs = [
"ext/transport/chaotic_good/frame.cc",
],
hdrs = [
"ext/transport/chaotic_good/frame.h",
],
external_deps = [
"absl/status",
"absl/status:statusor",
"absl/types:variant",
],
deps = [
"arena",
"bitset",
"chaotic_good_frame_header",
"context",
"no_destruct",
"slice",
"slice_buffer",
"status_helper",
"//:gpr",
"//:gpr_platform",
"//:grpc_base",
"//:hpack_encoder",
"//:hpack_parser",
],
)
grpc_cc_library(
name = "chaotic_good_frame_header",
srcs = [
"ext/transport/chaotic_good/frame_header.cc",
],
hdrs = [
"ext/transport/chaotic_good/frame_header.h",
],
external_deps = [
"absl/status",
"absl/status:statusor",
],
deps = [
"bitset",
"//:gpr_platform",
],
)
### UPB Targets
grpc_upb_proto_library(

@ -0,0 +1,307 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <grpc/support/port_platform.h>
#include "src/core/ext/transport/chaotic_good/frame.h"
#include <string.h>
#include <limits>
#include <utility>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include <grpc/slice.h>
#include <grpc/support/log.h>
#include "src/core/lib/gprpp/bitset.h"
#include "src/core/lib/gprpp/no_destruct.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
namespace grpc_core {
namespace chaotic_good {
namespace {
const NoDestruct<Slice> kZeroSlice{[] {
auto slice = GRPC_SLICE_MALLOC(64);
memset(GRPC_SLICE_START_PTR(slice), 0, 64);
return slice;
}()};
class FrameSerializer {
public:
explicit FrameSerializer(FrameType type, uint32_t stream_id)
: header_{type, {}, stream_id, 0, 0, 0} {
output_.AppendIndexed(kZeroSlice->Copy());
}
// If called, must be called before AddMessage, AddTrailers, Finish
SliceBuffer& AddHeaders() {
GPR_ASSERT(last_added_ == nullptr);
header_.flags.set(0);
return Start(&header_.header_length);
}
// If called, must be called before AddTrailers, Finish
SliceBuffer& AddMessage() {
MaybeCommitLast();
header_.flags.set(1);
return Start(&header_.message_length);
}
// If called, must be called before Finish
SliceBuffer& AddTrailers() {
MaybeCommitLast();
header_.flags.set(2);
return Start(&header_.trailer_length);
}
SliceBuffer Finish() {
MaybeCommitLast();
header_.Serialize(
GRPC_SLICE_START_PTR(output_.c_slice_buffer()->slices[0]));
return std::move(output_);
}
private:
SliceBuffer& Start(uint32_t* length_field) {
last_added_ = length_field;
length_at_last_added_ = output_.Length();
return output_;
}
void MaybeCommitLast() {
if (last_added_ == nullptr) return;
*last_added_ = output_.Length() - length_at_last_added_;
if (output_.Length() % 64 != 0) {
output_.Append(kZeroSlice->RefSubSlice(0, 64 - output_.Length() % 64));
}
}
FrameHeader header_;
uint32_t* last_added_ = nullptr;
size_t length_at_last_added_;
SliceBuffer output_;
};
class FrameDeserializer {
public:
FrameDeserializer(const FrameHeader& header, SliceBuffer& input)
: header_(header), input_(input) {}
const FrameHeader& header() const { return header_; }
// If called, must be called before ReceiveMessage, ReceiveTrailers
absl::StatusOr<SliceBuffer> ReceiveHeaders() {
return Take(header_.header_length);
}
// If called, must be called before ReceiveTrailers
absl::StatusOr<SliceBuffer> ReceiveMessage() {
return Take(header_.message_length);
}
// If called, must be called before Finish
absl::StatusOr<SliceBuffer> ReceiveTrailers() {
return Take(header_.trailer_length);
}
absl::Status Finish() { return absl::OkStatus(); }
private:
absl::StatusOr<SliceBuffer> Take(uint32_t length) {
if (length == 0) return SliceBuffer{};
if (input_.Length() < length) {
return absl::InvalidArgumentError(
"Frame too short (insufficient payload)");
}
SliceBuffer out;
input_.MoveFirstNBytesIntoSliceBuffer(length, out);
if (length % 64 != 0) {
const uint32_t padding_length = 64 - length % 64;
if (input_.Length() < padding_length) {
return absl::InvalidArgumentError(
"Frame too short (insufficient padding)");
}
uint8_t padding[64];
input_.MoveFirstNBytesIntoBuffer(padding_length, padding);
for (uint32_t i = 0; i < padding_length; i++) {
if (padding[i] != 0) {
return absl::InvalidArgumentError("Frame padding not zero");
}
}
}
return std::move(out);
}
FrameHeader header_;
SliceBuffer& input_;
};
template <typename Metadata>
absl::StatusOr<Arena::PoolPtr<Metadata>> ReadMetadata(
HPackParser* parser, absl::StatusOr<SliceBuffer> maybe_slices,
uint32_t stream_id, bool is_header, bool is_client) {
if (!maybe_slices.ok()) return maybe_slices.status();
auto& slices = *maybe_slices;
Arena::PoolPtr<Metadata> metadata;
parser->BeginFrame(
metadata.get(), std::numeric_limits<uint32_t>::max(),
is_header ? HPackParser::Boundary::EndOfHeaders
: HPackParser::Boundary::EndOfStream,
HPackParser::Priority::None,
HPackParser::LogInfo{stream_id,
is_header ? HPackParser::LogInfo::Type::kHeaders
: HPackParser::LogInfo::Type::kTrailers,
is_client});
for (size_t i = 0; i < slices.Count(); i++) {
GRPC_RETURN_IF_ERROR(
parser->Parse(slices.c_slice_at(i), i == slices.Count() - 1));
}
parser->FinishFrame();
return std::move(metadata);
}
} // namespace
absl::Status SettingsFrame::Deserialize(HPackParser*, const FrameHeader& header,
SliceBuffer& slice_buffer) {
if (header.type != FrameType::kSettings) {
return absl::InvalidArgumentError("Expected settings frame");
}
if (header.flags.any()) {
return absl::InvalidArgumentError("Unexpected flags");
}
FrameDeserializer deserializer(header, slice_buffer);
return deserializer.Finish();
}
SliceBuffer SettingsFrame::Serialize(HPackCompressor*) const {
FrameSerializer serializer(FrameType::kSettings, 0);
return serializer.Finish();
}
absl::Status ClientFragmentFrame::Deserialize(HPackParser* parser,
const FrameHeader& header,
SliceBuffer& slice_buffer) {
if (header.stream_id == 0) {
return absl::InvalidArgumentError("Expected non-zero stream id");
}
stream_id = header.stream_id;
if (header.type != FrameType::kFragment) {
return absl::InvalidArgumentError("Expected fragment frame");
}
FrameDeserializer deserializer(header, slice_buffer);
if (header.flags.is_set(0)) {
auto r = ReadMetadata<ClientMetadata>(parser, deserializer.ReceiveHeaders(),
header.stream_id, true, true);
if (!r.ok()) return r.status();
}
if (header.flags.is_set(1)) {
message = GetContext<Arena>()->MakePooled<Message>();
auto r = deserializer.ReceiveMessage();
if (!r.ok()) return r.status();
r->Swap(message->payload());
}
if (header.flags.is_set(2)) {
if (header.trailer_length != 0) {
return absl::InvalidArgumentError("Unexpected trailer length");
}
end_of_stream = true;
} else {
end_of_stream = false;
}
return deserializer.Finish();
}
SliceBuffer ClientFragmentFrame::Serialize(HPackCompressor* encoder) const {
GPR_ASSERT(stream_id != 0);
FrameSerializer serializer(FrameType::kFragment, stream_id);
if (headers.get() != nullptr) {
encoder->EncodeRawHeaders(*headers.get(), serializer.AddHeaders());
}
if (message.get() != nullptr) {
serializer.AddMessage().Append(*message->payload());
}
if (end_of_stream) {
serializer.AddTrailers();
}
return serializer.Finish();
}
absl::Status ServerFragmentFrame::Deserialize(HPackParser* parser,
const FrameHeader& header,
SliceBuffer& slice_buffer) {
if (header.stream_id == 0) {
return absl::InvalidArgumentError("Expected non-zero stream id");
}
stream_id = header.stream_id;
if (header.type != FrameType::kFragment) {
return absl::InvalidArgumentError("Expected fragment frame");
}
FrameDeserializer deserializer(header, slice_buffer);
if (header.flags.is_set(0)) {
auto r = ReadMetadata<ServerMetadata>(parser, deserializer.ReceiveHeaders(),
header.stream_id, true, false);
if (!r.ok()) return r.status();
}
if (header.flags.is_set(1)) {
message = GetContext<Arena>()->MakePooled<Message>();
auto r = deserializer.ReceiveMessage();
if (!r.ok()) return r.status();
r->Swap(message->payload());
}
if (header.flags.is_set(2)) {
auto r = ReadMetadata<ServerMetadata>(
parser, deserializer.ReceiveTrailers(), header.stream_id, false, false);
}
return deserializer.Finish();
}
SliceBuffer ServerFragmentFrame::Serialize(HPackCompressor* encoder) const {
GPR_ASSERT(stream_id != 0);
FrameSerializer serializer(FrameType::kFragment, stream_id);
if (headers.get() != nullptr) {
encoder->EncodeRawHeaders(*headers.get(), serializer.AddHeaders());
}
if (message.get() != nullptr) {
serializer.AddMessage().Append(*message->payload());
}
if (trailers.get() != nullptr) {
encoder->EncodeRawHeaders(*trailers.get(), serializer.AddTrailers());
}
return serializer.Finish();
}
absl::Status CancelFrame::Deserialize(HPackParser*, const FrameHeader& header,
SliceBuffer& slice_buffer) {
if (header.type != FrameType::kCancel) {
return absl::InvalidArgumentError("Expected cancel frame");
}
if (header.flags.any()) {
return absl::InvalidArgumentError("Unexpected flags");
}
if (header.stream_id == 0) {
return absl::InvalidArgumentError("Expected non-zero stream id");
}
FrameDeserializer deserializer(header, slice_buffer);
stream_id = header.stream_id;
return deserializer.Finish();
}
SliceBuffer CancelFrame::Serialize(HPackCompressor*) const {
GPR_ASSERT(stream_id != 0);
FrameSerializer serializer(FrameType::kCancel, stream_id);
return serializer.Finish();
}
} // namespace chaotic_good
} // namespace grpc_core

@ -0,0 +1,122 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GRPC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_H
#define GRPC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_H
#include <grpc/support/port_platform.h>
#include <cstdint>
#include <memory>
#include <string>
#include "absl/status/status.h"
#include "absl/types/variant.h"
#include "src/core/ext/transport/chaotic_good/frame_header.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
namespace chaotic_good {
class FrameInterface {
public:
virtual absl::Status Deserialize(HPackParser* parser,
const FrameHeader& header,
SliceBuffer& slice_buffer) = 0;
virtual SliceBuffer Serialize(HPackCompressor* encoder) const = 0;
protected:
static bool EqVal(const Message& a, const Message& b) {
return a.payload()->JoinIntoString() == b.payload()->JoinIntoString() &&
a.flags() == b.flags();
}
static bool EqVal(const grpc_metadata_batch& a,
const grpc_metadata_batch& b) {
return a.DebugString() == b.DebugString();
}
template <typename T>
static bool EqHdl(const Arena::PoolPtr<T>& a, const Arena::PoolPtr<T>& b) {
if (a == nullptr && b == nullptr) return true;
if (a == nullptr || b == nullptr) return false;
return EqVal(*a, *b);
}
~FrameInterface() = default;
};
struct SettingsFrame final : public FrameInterface {
absl::Status Deserialize(HPackParser* parser, const FrameHeader& header,
SliceBuffer& slice_buffer) override;
SliceBuffer Serialize(HPackCompressor* encoder) const override;
bool operator==(const SettingsFrame&) const { return true; }
};
struct ClientFragmentFrame final : public FrameInterface {
absl::Status Deserialize(HPackParser* parser, const FrameHeader& header,
SliceBuffer& slice_buffer) override;
SliceBuffer Serialize(HPackCompressor* encoder) const override;
uint32_t stream_id;
ClientMetadataHandle headers;
MessageHandle message;
bool end_of_stream = false;
bool operator==(const ClientFragmentFrame& other) const {
return stream_id == other.stream_id && EqHdl(headers, other.headers) &&
EqHdl(message, other.message) &&
end_of_stream == other.end_of_stream;
}
};
struct ServerFragmentFrame final : public FrameInterface {
absl::Status Deserialize(HPackParser* parser, const FrameHeader& header,
SliceBuffer& slice_buffer) override;
SliceBuffer Serialize(HPackCompressor* encoder) const override;
uint32_t stream_id;
ServerMetadataHandle headers;
MessageHandle message;
ServerMetadataHandle trailers;
bool operator==(const ServerFragmentFrame& other) const {
return stream_id == other.stream_id && EqHdl(headers, other.headers) &&
EqHdl(message, other.message) && EqHdl(trailers, other.trailers);
}
};
struct CancelFrame final : public FrameInterface {
absl::Status Deserialize(HPackParser* parser, const FrameHeader& header,
SliceBuffer& slice_buffer) override;
SliceBuffer Serialize(HPackCompressor* encoder) const override;
uint32_t stream_id;
bool operator==(const CancelFrame& other) const {
return stream_id == other.stream_id;
}
};
using ClientFrame = absl::variant<ClientFragmentFrame, CancelFrame>;
using ServerFrame = absl::variant<ServerFragmentFrame>;
} // namespace chaotic_good
} // namespace grpc_core
#endif // GRPC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_H

@ -0,0 +1,87 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <grpc/support/port_platform.h>
#include "src/core/ext/transport/chaotic_good/frame_header.h"
#include <string.h>
#include <cstdint>
#include "absl/status/status.h"
namespace grpc_core {
namespace chaotic_good {
namespace {
void WriteLittleEndianUint32(uint32_t value, uint8_t* data) {
data[0] = static_cast<uint8_t>(value);
data[1] = static_cast<uint8_t>(value >> 8);
data[2] = static_cast<uint8_t>(value >> 16);
data[3] = static_cast<uint8_t>(value >> 24);
}
uint32_t ReadLittleEndianUint32(const uint8_t* data) {
return static_cast<uint32_t>(data[0]) |
(static_cast<uint32_t>(data[1]) << 8) |
(static_cast<uint32_t>(data[2]) << 16) |
(static_cast<uint32_t>(data[3]) << 24);
}
} // namespace
void FrameHeader::Serialize(uint8_t* data) const {
WriteLittleEndianUint32(
static_cast<uint32_t>(type) | (flags.ToInt<uint32_t>() << 8), data);
WriteLittleEndianUint32(stream_id, data + 4);
WriteLittleEndianUint32(header_length, data + 8);
WriteLittleEndianUint32(message_length, data + 12);
WriteLittleEndianUint32(trailer_length, data + 16);
memset(data + 20, 0, 44);
}
absl::StatusOr<FrameHeader> FrameHeader::Parse(const uint8_t* data) {
FrameHeader header;
const uint32_t type_and_flags = ReadLittleEndianUint32(data);
header.type = static_cast<FrameType>(type_and_flags & 0xff);
const uint32_t flags = type_and_flags >> 8;
if (flags > 7) return absl::InvalidArgumentError("Invalid flags");
header.flags = BitSet<3>::FromInt(flags);
header.stream_id = ReadLittleEndianUint32(data + 4);
header.header_length = ReadLittleEndianUint32(data + 8);
header.message_length = ReadLittleEndianUint32(data + 12);
header.trailer_length = ReadLittleEndianUint32(data + 16);
for (int i = 0; i < 44; i++) {
if (data[20 + i] != 0) return absl::InvalidArgumentError("Invalid padding");
}
return header;
}
namespace {
uint64_t RoundUp(uint64_t x) {
if (x % 64 == 0) return x;
return x + 64 - (x % 64);
}
} // namespace
FrameSizes FrameHeader::ComputeFrameSizes() const {
FrameSizes sizes;
sizes.message_offset = RoundUp(header_length);
sizes.trailer_offset = sizes.message_offset + RoundUp(message_length);
sizes.frame_length = sizes.trailer_offset + RoundUp(trailer_length);
return sizes;
}
} // namespace chaotic_good
} // namespace grpc_core

@ -0,0 +1,73 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GRPC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_HEADER_H
#define GRPC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_HEADER_H
#include <grpc/support/port_platform.h>
#include <cstdint>
#include "absl/status/statusor.h"
#include "src/core/lib/gprpp/bitset.h"
namespace grpc_core {
namespace chaotic_good {
enum class FrameType : uint8_t {
kSettings = 0x00,
kFragment = 0x80,
kCancel = 0x81,
};
struct FrameSizes {
uint64_t message_offset;
uint64_t trailer_offset;
uint64_t frame_length;
bool operator==(const FrameSizes& other) const {
return message_offset == other.message_offset &&
trailer_offset == other.trailer_offset &&
frame_length == other.frame_length;
}
};
struct FrameHeader {
FrameType type;
BitSet<3> flags;
uint32_t stream_id;
uint32_t header_length;
uint32_t message_length;
uint32_t trailer_length;
// Parses a frame header from a buffer of 64 bytes. All 64 bytes are consumed.
static absl::StatusOr<FrameHeader> Parse(const uint8_t* data);
// Serializes a frame header into a buffer of 64 bytes.
void Serialize(uint8_t* data) const;
// Compute frame sizes from the header.
FrameSizes ComputeFrameSizes() const;
bool operator==(const FrameHeader& h) const {
return type == h.type && flags == h.flags && stream_id == h.stream_id &&
header_length == h.header_length &&
message_length == h.message_length &&
trailer_length == h.trailer_length;
}
};
} // namespace chaotic_good
} // namespace grpc_core
#endif // GRPC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_HEADER_H

@ -55,6 +55,7 @@
#include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/stream_map.h"
#include "src/core/ext/transport/chttp2/transport/varint.h"
@ -127,7 +128,6 @@ static int g_default_max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA;
static int g_default_max_ping_strikes = DEFAULT_MAX_PING_STRIKES;
#define MAX_CLIENT_STREAM_ID 0x7fffffffu
grpc_core::TraceFlag grpc_http_trace(false, "http");
grpc_core::TraceFlag grpc_keepalive_trace(false, "http_keepalive");
grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount(false,
"chttp2_refcount");

@ -31,7 +31,6 @@
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/transport/transport_fwd.h"
extern grpc_core::TraceFlag grpc_http_trace;
extern grpc_core::TraceFlag grpc_keepalive_trace;
extern grpc_core::TraceFlag grpc_trace_http2_stream_state;
extern grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount;

@ -30,7 +30,7 @@
#include <grpc/support/log.h>
#include "src/core/ext/transport/chttp2/transport/frame.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/status_helper.h"

@ -34,7 +34,7 @@
#include "src/core/ext/transport/chttp2/transport/flow_control.h"
#include "src/core/ext/transport/chttp2/transport/frame.h"
#include "src/core/ext/transport/chttp2/transport/frame_goaway.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gpr/useful.h"

@ -31,7 +31,9 @@
#include "src/core/ext/transport/chttp2/transport/frame.h"
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder_table.h"
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
#include "src/core/ext/transport/chttp2/transport/varint.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/surface/validate_metadata.h"
#include "src/core/lib/transport/timeout_encoding.h"
@ -59,7 +61,7 @@ static void FillHeader(uint8_t* p, uint8_t type, uint32_t id, size_t len,
max_frame_size is derived from GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
which has a max allowable value of 16777215 (see chttp_transport.cc).
Thus, the following assert can be a debug assert. */
GPR_DEBUG_ASSERT(len < 16777316);
GPR_DEBUG_ASSERT(len <= 16777216);
*p++ = static_cast<uint8_t>(len >> 16);
*p++ = static_cast<uint8_t>(len >> 8);
*p++ = static_cast<uint8_t>(len);
@ -71,17 +73,9 @@ static void FillHeader(uint8_t* p, uint8_t type, uint32_t id, size_t len,
*p++ = static_cast<uint8_t>(id);
}
size_t HPackCompressor::Framer::CurrentFrameSize() const {
const size_t frame_size =
output_->length - prefix_.output_length_at_start_of_frame;
GPR_DEBUG_ASSERT(frame_size <= max_frame_size_);
return frame_size;
}
// finish a frame - fill in the previously reserved header
void HPackCompressor::Framer::FinishFrame(bool is_header_boundary) {
const uint8_t type = is_first_frame_ ? GRPC_CHTTP2_FRAME_HEADER
: GRPC_CHTTP2_FRAME_CONTINUATION;
void HPackCompressor::Frame(const EncodeHeaderOptions& options,
SliceBuffer& raw, grpc_slice_buffer* output) {
uint8_t frame_type = GRPC_CHTTP2_FRAME_HEADER;
uint8_t flags = 0;
// per the HTTP/2 spec:
// A HEADERS frame carries the END_STREAM flag that signals the end of a
@ -89,72 +83,34 @@ void HPackCompressor::Framer::FinishFrame(bool is_header_boundary) {
// followed by CONTINUATION frames on the same stream. Logically, the
// CONTINUATION frames are part of the HEADERS frame.
// Thus, we add the END_STREAM flag to the HEADER frame (the first frame).
if (is_first_frame_ && is_end_of_stream_) {
if (options.is_end_of_stream) {
flags |= GRPC_CHTTP2_DATA_FLAG_END_STREAM;
}
// per the HTTP/2 spec:
// A HEADERS frame without the END_HEADERS flag set MUST be followed by
// a CONTINUATION frame for the same stream.
// Thus, we add the END_HEADER flag to the last frame.
if (is_header_boundary) {
flags |= GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
}
FillHeader(GRPC_SLICE_START_PTR(output_->slices[prefix_.header_idx]), type,
stream_id_, CurrentFrameSize(), flags);
stats_->framing_bytes += kDataFrameHeaderSize;
is_first_frame_ = false;
}
// begin a new frame: reserve off header space, remember how many bytes we'd
// output before beginning
HPackCompressor::Framer::FramePrefix HPackCompressor::Framer::BeginFrame() {
grpc_slice reserved;
reserved.refcount = nullptr;
reserved.data.inlined.length = kDataFrameHeaderSize;
return FramePrefix{grpc_slice_buffer_add_indexed(output_, reserved),
output_->length};
}
// make sure that the current frame is of the type desired, and has sufficient
// space to add at least about_to_add bytes -- finishes the current frame if
// needed
void HPackCompressor::Framer::EnsureSpace(size_t need_bytes) {
if (GPR_LIKELY(CurrentFrameSize() + need_bytes <= max_frame_size_)) {
return;
}
FinishFrame(false);
prefix_ = BeginFrame();
}
void HPackCompressor::Framer::Add(Slice slice) {
while (true) {
const size_t len = slice.length();
if (len == 0) return;
const size_t remaining = max_frame_size_ - CurrentFrameSize();
if (len <= remaining) {
stats_->header_bytes += len;
grpc_slice_buffer_add(output_, slice.TakeCSlice());
return;
options.stats->header_bytes += raw.Length();
while (frame_type == GRPC_CHTTP2_FRAME_HEADER || raw.Length() > 0) {
// per the HTTP/2 spec:
// A HEADERS frame without the END_HEADERS flag set MUST be followed by
// a CONTINUATION frame for the same stream.
// Thus, we add the END_HEADER flag to the last frame.
size_t len = raw.Length();
if (len <= options.max_frame_size) {
flags |= GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
} else {
stats_->header_bytes += remaining;
Slice tail = slice.Split(remaining);
grpc_slice_buffer_add(output_, slice.TakeCSlice());
slice = std::move(tail);
FinishFrame(false);
prefix_ = BeginFrame();
len = options.max_frame_size;
}
}
}
FillHeader(grpc_slice_buffer_tiny_add(output, kDataFrameHeaderSize),
frame_type, options.stream_id, len, flags);
options.stats->framing_bytes += kDataFrameHeaderSize;
grpc_slice_buffer_move_first(raw.c_slice_buffer(), len, output);
uint8_t* HPackCompressor::Framer::AddTiny(size_t len) {
EnsureSpace(len);
stats_->header_bytes += len;
return grpc_slice_buffer_tiny_add(output_, len);
frame_type = GRPC_CHTTP2_FRAME_CONTINUATION;
flags = 0;
}
}
void HPackCompressor::Framer::EmitIndexed(uint32_t elem_index) {
void HPackCompressor::Encoder::EmitIndexed(uint32_t elem_index) {
VarintWriter<1> w(elem_index);
w.Write(0x80, AddTiny(w.length()));
w.Write(0x80, output_.AddTiny(w.length()));
}
struct WireValue {
@ -258,71 +214,71 @@ class StringKey {
VarintWriter<1> len_key_;
};
void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyIncIdx(
void HPackCompressor::Encoder::EmitLitHdrWithNonBinaryStringKeyIncIdx(
Slice key_slice, Slice value_slice) {
StringKey key(std::move(key_slice));
key.WritePrefix(0x40, AddTiny(key.prefix_length()));
Add(key.key());
key.WritePrefix(0x40, output_.AddTiny(key.prefix_length()));
output_.Append(key.key());
NonBinaryStringValue emit(std::move(value_slice));
emit.WritePrefix(AddTiny(emit.prefix_length()));
Add(emit.data());
emit.WritePrefix(output_.AddTiny(emit.prefix_length()));
output_.Append(emit.data());
}
void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyNotIdx(
void HPackCompressor::Encoder::EmitLitHdrWithBinaryStringKeyNotIdx(
Slice key_slice, Slice value_slice) {
StringKey key(std::move(key_slice));
key.WritePrefix(0x00, AddTiny(key.prefix_length()));
Add(key.key());
key.WritePrefix(0x00, output_.AddTiny(key.prefix_length()));
output_.Append(key.key());
BinaryStringValue emit(std::move(value_slice), use_true_binary_metadata_);
emit.WritePrefix(AddTiny(emit.prefix_length()));
Add(emit.data());
emit.WritePrefix(output_.AddTiny(emit.prefix_length()));
output_.Append(emit.data());
}
void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyIncIdx(
void HPackCompressor::Encoder::EmitLitHdrWithBinaryStringKeyIncIdx(
Slice key_slice, Slice value_slice) {
StringKey key(std::move(key_slice));
key.WritePrefix(0x40, AddTiny(key.prefix_length()));
Add(key.key());
key.WritePrefix(0x40, output_.AddTiny(key.prefix_length()));
output_.Append(key.key());
BinaryStringValue emit(std::move(value_slice), use_true_binary_metadata_);
emit.WritePrefix(AddTiny(emit.prefix_length()));
Add(emit.data());
emit.WritePrefix(output_.AddTiny(emit.prefix_length()));
output_.Append(emit.data());
}
void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyNotIdx(
void HPackCompressor::Encoder::EmitLitHdrWithBinaryStringKeyNotIdx(
uint32_t key_index, Slice value_slice) {
BinaryStringValue emit(std::move(value_slice), use_true_binary_metadata_);
VarintWriter<4> key(key_index);
uint8_t* data = AddTiny(key.length() + emit.prefix_length());
uint8_t* data = output_.AddTiny(key.length() + emit.prefix_length());
key.Write(0x00, data);
emit.WritePrefix(data + key.length());
Add(emit.data());
output_.Append(emit.data());
}
void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyNotIdx(
void HPackCompressor::Encoder::EmitLitHdrWithNonBinaryStringKeyNotIdx(
Slice key_slice, Slice value_slice) {
StringKey key(std::move(key_slice));
key.WritePrefix(0x00, AddTiny(key.prefix_length()));
Add(key.key());
key.WritePrefix(0x00, output_.AddTiny(key.prefix_length()));
output_.Append(key.key());
NonBinaryStringValue emit(std::move(value_slice));
emit.WritePrefix(AddTiny(emit.prefix_length()));
Add(emit.data());
emit.WritePrefix(output_.AddTiny(emit.prefix_length()));
output_.Append(emit.data());
}
void HPackCompressor::Framer::AdvertiseTableSizeChange() {
void HPackCompressor::Encoder::AdvertiseTableSizeChange() {
VarintWriter<3> w(compressor_->table_.max_size());
w.Write(0x20, AddTiny(w.length()));
w.Write(0x20, output_.AddTiny(w.length()));
}
void HPackCompressor::SliceIndex::EmitTo(absl::string_view key,
const Slice& value, Framer* framer) {
auto& table = framer->compressor_->table_;
const Slice& value, Encoder* encoder) {
auto& table = encoder->compressor_->table_;
using It = std::vector<ValueIndex>::iterator;
It prev = values_.end();
size_t transport_length =
key.length() + value.length() + hpack_constants::kEntryOverhead;
if (transport_length > HPackEncoderTable::MaxEntrySize()) {
framer->EmitLitHdrWithNonBinaryStringKeyNotIdx(Slice::FromStaticString(key),
value.Ref());
encoder->EmitLitHdrWithNonBinaryStringKeyNotIdx(
Slice::FromStaticString(key), value.Ref());
return;
}
// Linear scan through previous values to see if we find the value.
@ -331,11 +287,11 @@ void HPackCompressor::SliceIndex::EmitTo(absl::string_view key,
// Got a hit... is it still in the decode table?
if (table.ConvertableToDynamicIndex(it->index)) {
// Yes, emit the index and proceed to cleanup.
framer->EmitIndexed(table.DynamicIndex(it->index));
encoder->EmitIndexed(table.DynamicIndex(it->index));
} else {
// Not current, emit a new literal and update the index.
it->index = table.AllocateIndex(transport_length);
framer->EmitLitHdrWithNonBinaryStringKeyIncIdx(
encoder->EmitLitHdrWithNonBinaryStringKeyIncIdx(
Slice::FromStaticString(key), value.Ref());
}
// Bubble this entry up if we can - ensures that the most used values end
@ -354,12 +310,12 @@ void HPackCompressor::SliceIndex::EmitTo(absl::string_view key,
}
// No hit, emit a new literal and add it to the index.
uint32_t index = table.AllocateIndex(transport_length);
framer->EmitLitHdrWithNonBinaryStringKeyIncIdx(Slice::FromStaticString(key),
value.Ref());
encoder->EmitLitHdrWithNonBinaryStringKeyIncIdx(Slice::FromStaticString(key),
value.Ref());
values_.emplace_back(value.Ref(), index);
}
void HPackCompressor::Framer::Encode(const Slice& key, const Slice& value) {
void HPackCompressor::Encoder::Encode(const Slice& key, const Slice& value) {
if (absl::EndsWith(key.as_string_view(), "-bin")) {
EmitLitHdrWithBinaryStringKeyNotIdx(key.Ref(), value.Ref());
} else {
@ -367,25 +323,25 @@ void HPackCompressor::Framer::Encode(const Slice& key, const Slice& value) {
}
}
void HPackCompressor::Framer::Encode(HttpPathMetadata, const Slice& value) {
void HPackCompressor::Encoder::Encode(HttpPathMetadata, const Slice& value) {
compressor_->path_index_.EmitTo(HttpPathMetadata::key(), value, this);
}
void HPackCompressor::Framer::Encode(HttpAuthorityMetadata,
const Slice& value) {
void HPackCompressor::Encoder::Encode(HttpAuthorityMetadata,
const Slice& value) {
compressor_->authority_index_.EmitTo(HttpAuthorityMetadata::key(), value,
this);
}
void HPackCompressor::Framer::Encode(TeMetadata, TeMetadata::ValueType value) {
void HPackCompressor::Encoder::Encode(TeMetadata, TeMetadata::ValueType value) {
GPR_ASSERT(value == TeMetadata::ValueType::kTrailers);
EncodeAlwaysIndexed(
&compressor_->te_index_, "te", Slice::FromStaticString("trailers"),
2 /* te */ + 8 /* trailers */ + hpack_constants::kEntryOverhead);
}
void HPackCompressor::Framer::Encode(ContentTypeMetadata,
ContentTypeMetadata::ValueType value) {
void HPackCompressor::Encoder::Encode(ContentTypeMetadata,
ContentTypeMetadata::ValueType value) {
if (value != ContentTypeMetadata::ValueType::kApplicationGrpc) {
gpr_log(GPR_ERROR, "Not encoding bad content-type header");
return;
@ -396,8 +352,8 @@ void HPackCompressor::Framer::Encode(ContentTypeMetadata,
hpack_constants::kEntryOverhead);
}
void HPackCompressor::Framer::Encode(HttpSchemeMetadata,
HttpSchemeMetadata::ValueType value) {
void HPackCompressor::Encoder::Encode(HttpSchemeMetadata,
HttpSchemeMetadata::ValueType value) {
switch (value) {
case HttpSchemeMetadata::ValueType::kHttp:
EmitIndexed(6); // :scheme: http
@ -411,19 +367,20 @@ void HPackCompressor::Framer::Encode(HttpSchemeMetadata,
}
}
void HPackCompressor::Framer::Encode(GrpcTraceBinMetadata, const Slice& slice) {
void HPackCompressor::Encoder::Encode(GrpcTraceBinMetadata,
const Slice& slice) {
EncodeRepeatingSliceValue(GrpcTraceBinMetadata::key(), slice,
&compressor_->grpc_trace_bin_index_,
HPackEncoderTable::MaxEntrySize());
}
void HPackCompressor::Framer::Encode(GrpcTagsBinMetadata, const Slice& slice) {
void HPackCompressor::Encoder::Encode(GrpcTagsBinMetadata, const Slice& slice) {
EncodeRepeatingSliceValue(GrpcTagsBinMetadata::key(), slice,
&compressor_->grpc_tags_bin_index_,
HPackEncoderTable::MaxEntrySize());
}
void HPackCompressor::Framer::Encode(HttpStatusMetadata, uint32_t status) {
void HPackCompressor::Encoder::Encode(HttpStatusMetadata, uint32_t status) {
if (status == 200) {
EmitIndexed(8); // :status: 200
return;
@ -457,8 +414,8 @@ void HPackCompressor::Framer::Encode(HttpStatusMetadata, uint32_t status) {
}
}
void HPackCompressor::Framer::Encode(HttpMethodMetadata,
HttpMethodMetadata::ValueType method) {
void HPackCompressor::Encoder::Encode(HttpMethodMetadata,
HttpMethodMetadata::ValueType method) {
switch (method) {
case HttpMethodMetadata::ValueType::kPost:
EmitIndexed(3); // :method: POST
@ -478,10 +435,10 @@ void HPackCompressor::Framer::Encode(HttpMethodMetadata,
}
}
void HPackCompressor::Framer::EncodeAlwaysIndexed(uint32_t* index,
absl::string_view key,
Slice value,
size_t transport_length) {
void HPackCompressor::Encoder::EncodeAlwaysIndexed(uint32_t* index,
absl::string_view key,
Slice value,
size_t transport_length) {
if (compressor_->table_.ConvertableToDynamicIndex(*index)) {
EmitIndexed(compressor_->table_.DynamicIndex(*index));
} else {
@ -491,7 +448,7 @@ void HPackCompressor::Framer::EncodeAlwaysIndexed(uint32_t* index,
}
}
void HPackCompressor::Framer::EncodeIndexedKeyWithBinaryValue(
void HPackCompressor::Encoder::EncodeIndexedKeyWithBinaryValue(
uint32_t* index, absl::string_view key, Slice value) {
if (compressor_->table_.ConvertableToDynamicIndex(*index)) {
EmitLitHdrWithBinaryStringKeyNotIdx(
@ -504,7 +461,7 @@ void HPackCompressor::Framer::EncodeIndexedKeyWithBinaryValue(
}
}
void HPackCompressor::Framer::EncodeRepeatingSliceValue(
void HPackCompressor::Encoder::EncodeRepeatingSliceValue(
const absl::string_view& key, const Slice& slice, uint32_t* index,
size_t max_compression_size) {
if (hpack_constants::SizeForEntry(key.size(), slice.size()) >
@ -516,7 +473,7 @@ void HPackCompressor::Framer::EncodeRepeatingSliceValue(
}
}
void HPackCompressor::Framer::Encode(GrpcTimeoutMetadata, Timestamp deadline) {
void HPackCompressor::Encoder::Encode(GrpcTimeoutMetadata, Timestamp deadline) {
Timeout timeout = Timeout::FromDuration(deadline - Timestamp::Now());
for (auto it = compressor_->previous_timeouts_.begin();
it != compressor_->previous_timeouts_.end(); ++it) {
@ -547,7 +504,7 @@ void HPackCompressor::Framer::Encode(GrpcTimeoutMetadata, Timestamp deadline) {
Slice::FromStaticString(GrpcTimeoutMetadata::key()), std::move(encoded));
}
void HPackCompressor::Framer::Encode(UserAgentMetadata, const Slice& slice) {
void HPackCompressor::Encoder::Encode(UserAgentMetadata, const Slice& slice) {
if (hpack_constants::SizeForEntry(UserAgentMetadata::key().size(),
slice.size()) >
HPackEncoderTable::MaxEntrySize()) {
@ -565,8 +522,8 @@ void HPackCompressor::Framer::Encode(UserAgentMetadata, const Slice& slice) {
UserAgentMetadata::key().size(), slice.size()));
}
void HPackCompressor::Framer::Encode(GrpcStatusMetadata,
grpc_status_code status) {
void HPackCompressor::Encoder::Encode(GrpcStatusMetadata,
grpc_status_code status) {
const uint32_t code = static_cast<uint32_t>(status);
uint32_t* index = nullptr;
if (code < kNumCachedGrpcStatusValues) {
@ -588,8 +545,8 @@ void HPackCompressor::Framer::Encode(GrpcStatusMetadata,
}
}
void HPackCompressor::Framer::Encode(GrpcEncodingMetadata,
grpc_compression_algorithm value) {
void HPackCompressor::Encoder::Encode(GrpcEncodingMetadata,
grpc_compression_algorithm value) {
uint32_t* index = nullptr;
if (value < GRPC_COMPRESS_ALGORITHMS_COUNT) {
index = &compressor_->cached_grpc_encoding_[static_cast<uint32_t>(value)];
@ -612,8 +569,8 @@ void HPackCompressor::Framer::Encode(GrpcEncodingMetadata,
}
}
void HPackCompressor::Framer::Encode(GrpcAcceptEncodingMetadata,
CompressionAlgorithmSet value) {
void HPackCompressor::Encoder::Encode(GrpcAcceptEncodingMetadata,
CompressionAlgorithmSet value) {
if (compressor_->grpc_accept_encoding_index_ != 0 &&
value == compressor_->grpc_accept_encoding_ &&
compressor_->table_.ConvertableToDynamicIndex(
@ -648,17 +605,12 @@ void HPackCompressor::SetMaxTableSize(uint32_t max_table_size) {
}
}
HPackCompressor::Framer::Framer(const EncodeHeaderOptions& options,
HPackCompressor* compressor,
grpc_slice_buffer* output)
: max_frame_size_(options.max_frame_size),
use_true_binary_metadata_(options.use_true_binary_metadata),
is_end_of_stream_(options.is_end_of_stream),
stream_id_(options.stream_id),
output_(output),
stats_(options.stats),
HPackCompressor::Encoder::Encoder(HPackCompressor* compressor,
bool use_true_binary_metadata,
SliceBuffer& output)
: use_true_binary_metadata_(use_true_binary_metadata),
compressor_(compressor),
prefix_(BeginFrame()) {
output_(output) {
if (std::exchange(compressor_->advertise_table_size_change_, false)) {
AdvertiseTableSizeChange();
}

@ -37,15 +37,13 @@
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder_table.h"
#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/timeout_encoding.h"
#include "src/core/lib/transport/transport.h"
extern grpc_core::TraceFlag grpc_http_trace;
namespace grpc_core {
class HPackCompressor {
@ -76,18 +74,23 @@ class HPackCompressor {
template <typename HeaderSet>
void EncodeHeaders(const EncodeHeaderOptions& options,
const HeaderSet& headers, grpc_slice_buffer* output) {
Framer framer(options, this, output);
headers.Encode(&framer);
SliceBuffer raw;
Encoder encoder(this, options.use_true_binary_metadata, raw);
headers.Encode(&encoder);
Frame(options, raw, output);
}
class Framer {
public:
Framer(const EncodeHeaderOptions& options, HPackCompressor* compressor,
grpc_slice_buffer* output);
~Framer() { FinishFrame(true); }
template <typename HeaderSet>
void EncodeRawHeaders(const HeaderSet& headers, SliceBuffer& output) {
Encoder encoder(this, true, output);
headers.Encode(&encoder);
}
Framer(const Framer&) = delete;
Framer& operator=(const Framer&) = delete;
private:
class Encoder {
public:
Encoder(HPackCompressor* compressor, bool use_true_binary_metadata,
SliceBuffer& output);
void Encode(const Slice& key, const Slice& value);
void Encode(HttpPathMetadata, const Slice& value);
@ -124,18 +127,6 @@ class HPackCompressor {
private:
friend class SliceIndex;
struct FramePrefix {
// index (in output_) of the header for the frame
size_t header_idx;
// number of bytes in 'output' when we started the frame - used to
// calculate frame length
size_t output_length_at_start_of_frame;
};
FramePrefix BeginFrame();
void FinishFrame(bool is_header_boundary);
void EnsureSpace(size_t need_bytes);
void AdvertiseTableSizeChange();
void EmitIndexed(uint32_t index);
void EmitLitHdrWithNonBinaryStringKeyIncIdx(Slice key_slice,
@ -158,27 +149,17 @@ class HPackCompressor {
const Slice& slice, uint32_t* index,
size_t max_compression_size);
size_t CurrentFrameSize() const;
void Add(Slice slice);
uint8_t* AddTiny(size_t len);
// maximum size of a frame
const size_t max_frame_size_;
bool is_first_frame_ = true;
const bool use_true_binary_metadata_;
const bool is_end_of_stream_;
// output stream id
const uint32_t stream_id_;
grpc_slice_buffer* const output_;
grpc_transport_one_way_stats* const stats_;
HPackCompressor* const compressor_;
FramePrefix prefix_;
SliceBuffer& output_;
};
private:
static constexpr size_t kNumFilterValues = 64;
static constexpr uint32_t kNumCachedGrpcStatusValues = 16;
void Frame(const EncodeHeaderOptions& options, SliceBuffer& raw,
grpc_slice_buffer* output);
// maximum number of bytes we'll use for the decode table (to guard against
// peers ooming us by setting decode table size high)
uint32_t max_usable_size_ = hpack_constants::kInitialTableSize;
@ -189,7 +170,7 @@ class HPackCompressor {
class SliceIndex {
public:
void EmitTo(absl::string_view key, const Slice& value, Framer* framer);
void EmitTo(absl::string_view key, const Slice& value, Encoder* encoder);
private:
struct ValueIndex {

@ -43,19 +43,13 @@
#include <grpc/support/log.h>
#include "src/core/ext/transport/chttp2/transport/decode_huff.h"
#include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h"
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_refcount.h"
#include "src/core/lib/transport/http2_errors.h"
#include "src/core/lib/transport/parsed_metadata.h"
#include "src/core/lib/transport/transport.h"
// IWYU pragma: no_include <type_traits>
@ -1314,69 +1308,3 @@ bool HPackParser::ParseInputInner(Input* input) {
void HPackParser::FinishFrame() { metadata_buffer_ = nullptr; }
} // namespace grpc_core
// TODO(ctiller): this serves as an eviction notice for the remainder of this
// file... it belongs elsewhere!
typedef void (*maybe_complete_func_type)(grpc_chttp2_transport* t,
grpc_chttp2_stream* s);
static const maybe_complete_func_type maybe_complete_funcs[] = {
grpc_chttp2_maybe_complete_recv_initial_metadata,
grpc_chttp2_maybe_complete_recv_trailing_metadata};
static void force_client_rst_stream(void* sp, grpc_error_handle /*error*/) {
grpc_chttp2_stream* s = static_cast<grpc_chttp2_stream*>(sp);
grpc_chttp2_transport* t = s->t;
if (!s->write_closed) {
grpc_chttp2_add_rst_stream_to_next_write(t, s->id, GRPC_HTTP2_NO_ERROR,
&s->stats.outgoing);
grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM);
grpc_chttp2_mark_stream_closed(t, s, true, true, absl::OkStatus());
}
GRPC_CHTTP2_STREAM_UNREF(s, "final_rst");
}
grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser,
grpc_chttp2_transport* t,
grpc_chttp2_stream* s,
const grpc_slice& slice,
int is_last) {
auto* parser = static_cast<grpc_core::HPackParser*>(hpack_parser);
if (s != nullptr) {
s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice);
}
grpc_error_handle error = parser->Parse(slice, is_last != 0);
if (!error.ok()) {
return error;
}
if (is_last) {
/* need to check for null stream: this can occur if we receive an invalid
stream id on a header */
if (s != nullptr) {
if (parser->is_boundary()) {
if (s->header_frames_received == 2) {
return GRPC_ERROR_CREATE("Too many trailer frames");
}
s->published_metadata[s->header_frames_received] =
GRPC_METADATA_PUBLISHED_FROM_WIRE;
maybe_complete_funcs[s->header_frames_received](t, s);
s->header_frames_received++;
}
if (parser->is_eof()) {
if (t->is_client && !s->write_closed) {
/* server eof ==> complete closure; we may need to forcefully close
the stream. Wait until the combiner lock is ready to be released
however -- it might be that we receive a RST_STREAM following this
and can avoid the extra write */
GRPC_CHTTP2_STREAM_REF(s, "final_rst");
t->combiner->FinallyRun(
GRPC_CLOSURE_CREATE(force_client_rst_stream, s, nullptr),
absl::OkStatus());
}
grpc_chttp2_mark_stream_closed(t, s, true, false, absl::OkStatus());
}
}
parser->FinishFrame();
}
return absl::OkStatus();
}

@ -34,11 +34,10 @@
#include <grpc/support/log.h>
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/slice/slice.h"
extern grpc_core::TraceFlag grpc_http_trace;
namespace grpc_core {
void HPackTable::MementoRingBuffer::Put(Memento m) {

@ -0,0 +1,19 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <grpc/support/port_platform.h>
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
grpc_core::TraceFlag grpc_http_trace(false, "http");

@ -0,0 +1,24 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP_TRACE_H
#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP_TRACE_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/debug/trace.h"
extern grpc_core::TraceFlag grpc_http_trace;
#endif // GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP_TRACE_H

@ -697,7 +697,6 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
(sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
// extern grpc_core::TraceFlag grpc_http_trace;
// extern grpc_core::TraceFlag grpc_flowctl_trace;
#define GRPC_CHTTP2_IF_TRACING(stmt) \

@ -39,10 +39,10 @@
#include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h"
#include "src/core/ext/transport/chttp2/transport/frame_settings.h"
#include "src/core/ext/transport/chttp2/transport/frame_window_update.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h"
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/stream_map.h"
#include "src/core/lib/channel/channelz.h"
@ -50,6 +50,8 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/transport/bdp_estimator.h"
#include "src/core/lib/transport/error_utils.h"
@ -728,3 +730,66 @@ static grpc_error_handle parse_frame_slice(grpc_chttp2_transport* t,
}
return err;
}
typedef void (*maybe_complete_func_type)(grpc_chttp2_transport* t,
grpc_chttp2_stream* s);
static const maybe_complete_func_type maybe_complete_funcs[] = {
grpc_chttp2_maybe_complete_recv_initial_metadata,
grpc_chttp2_maybe_complete_recv_trailing_metadata};
static void force_client_rst_stream(void* sp, grpc_error_handle /*error*/) {
grpc_chttp2_stream* s = static_cast<grpc_chttp2_stream*>(sp);
grpc_chttp2_transport* t = s->t;
if (!s->write_closed) {
grpc_chttp2_add_rst_stream_to_next_write(t, s->id, GRPC_HTTP2_NO_ERROR,
&s->stats.outgoing);
grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM);
grpc_chttp2_mark_stream_closed(t, s, true, true, absl::OkStatus());
}
GRPC_CHTTP2_STREAM_UNREF(s, "final_rst");
}
grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser,
grpc_chttp2_transport* t,
grpc_chttp2_stream* s,
const grpc_slice& slice,
int is_last) {
auto* parser = static_cast<grpc_core::HPackParser*>(hpack_parser);
if (s != nullptr) {
s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice);
}
grpc_error_handle error = parser->Parse(slice, is_last != 0);
if (!error.ok()) {
return error;
}
if (is_last) {
/* need to check for null stream: this can occur if we receive an invalid
stream id on a header */
if (s != nullptr) {
if (parser->is_boundary()) {
if (s->header_frames_received == 2) {
return GRPC_ERROR_CREATE("Too many trailer frames");
}
s->published_metadata[s->header_frames_received] =
GRPC_METADATA_PUBLISHED_FROM_WIRE;
maybe_complete_funcs[s->header_frames_received](t, s);
s->header_frames_received++;
}
if (parser->is_eof()) {
if (t->is_client && !s->write_closed) {
/* server eof ==> complete closure; we may need to forcefully close
the stream. Wait until the combiner lock is ready to be released
however -- it might be that we receive a RST_STREAM following this
and can avoid the extra write */
GRPC_CHTTP2_STREAM_REF(s, "final_rst");
t->combiner->FinallyRun(
GRPC_CLOSURE_CREATE(force_client_rst_stream, s, nullptr),
absl::OkStatus());
}
grpc_chttp2_mark_stream_closed(t, s, true, false, absl::OkStatus());
}
}
parser->FinishFrame();
}
return absl::OkStatus();
}

@ -32,6 +32,8 @@
#include <grpc/status.h>
#include <grpc/support/log.h>
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
// IWYU pragma: no_include "src/core/lib/gprpp/orphanable.h"
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"

@ -131,6 +131,9 @@ class BitSet {
return true;
}
// Returns true if any bites are set.
bool any() const { return !none(); }
// Return a count of how many bits are set.
uint32_t count() const {
uint32_t count = 0;
@ -159,6 +162,15 @@ class BitSet {
return result;
}
template <typename Int>
static BitSet<kTotalBits, kUnitBits> FromInt(Int value) {
BitSet<kTotalBits, kUnitBits> result;
for (size_t i = 0; i < kTotalBits; i++) {
result.set(i, (value & (Int(1) << i)) != 0);
}
return result;
}
private:
// Given a bit index, return which unit it's stored in.
static constexpr size_t unit_for(size_t bit) { return bit / kUnitBits; }

@ -38,6 +38,7 @@
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/timer_manager.h"
#include "src/core/lib/iomgr/wakeup_fd_posix.h"
#include "src/core/lib/surface/init_internally.h"
/*
* NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
@ -53,7 +54,7 @@ void grpc_prefork() {
skipped_handler = true;
// This may be called after core shuts down, so verify initialized before
// instantiating an ExecCtx.
if (!grpc_is_initialized()) {
if (!grpc_core::IsInitializedInternally()) {
return;
}
grpc_core::ExecCtx exec_ctx;

@ -194,6 +194,10 @@ struct CopyConstructors {
static Out FromCopiedBuffer(const char* p, size_t len) {
return Out(grpc_slice_from_copied_buffer(p, len));
}
static Out FromCopiedBuffer(const uint8_t* p, size_t len) {
return Out(
grpc_slice_from_copied_buffer(reinterpret_cast<const char*>(p), len));
}
template <typename Buffer>
static Out FromCopiedBuffer(const Buffer& buffer) {

@ -22,7 +22,6 @@
#include <string.h>
#include <cstdint>
#include <utility>
#include <grpc/slice.h>
@ -38,6 +37,12 @@ void SliceBuffer::Append(Slice slice) {
grpc_slice_buffer_add(&slice_buffer_, slice.TakeCSlice());
}
void SliceBuffer::Append(const SliceBuffer& other) {
for (size_t i = 0; i < other.Count(); i++) {
Append(other.RefSlice(i));
}
}
size_t SliceBuffer::AppendIndexed(Slice slice) {
return grpc_slice_buffer_add_indexed(&slice_buffer_, slice.TakeCSlice());
}

@ -17,6 +17,7 @@
#include <grpc/support/port_platform.h>
#include <stdint.h>
#include <string.h>
#include <string>
@ -62,6 +63,9 @@ class SliceBuffer {
/// Appends a new slice into the SliceBuffer and makes an attempt to merge
/// this slice with the last slice in the SliceBuffer.
void Append(Slice slice);
/// Appends a SliceBuffer into the SliceBuffer and makes an attempt to merge
/// this slice with the last slice in the SliceBuffer.
void Append(const SliceBuffer& other);
/// Adds a new slice into the SliceBuffer at the next available index.
/// Returns the index at which the new slice is added.
@ -80,6 +84,17 @@ class SliceBuffer {
grpc_slice_buffer_move_first_into_buffer(&slice_buffer_, n, dst);
}
/// Removes/deletes the last n bytes in the SliceBuffer and add it to the
/// other SliceBuffer
void MoveLastNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
grpc_slice_buffer_trim_end(&slice_buffer_, n, &other.slice_buffer_);
}
/// Move the first n bytes of the SliceBuffer into the other SliceBuffer
void MoveFirstNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
grpc_slice_buffer_move_first(&slice_buffer_, n, &other.slice_buffer_);
}
/// Removes and unrefs all slices in the SliceBuffer.
void Clear() { grpc_slice_buffer_reset_and_unref(&slice_buffer_); }
@ -113,6 +128,11 @@ class SliceBuffer {
return copy;
}
/// Add a small amount to the end of the slice buffer.
uint8_t* AddTiny(size_t n) {
return grpc_slice_buffer_tiny_add(&slice_buffer_, n);
}
/// Return a pointer to the back raw grpc_slice_buffer
grpc_slice_buffer* c_slice_buffer() { return &slice_buffer_; }

@ -118,6 +118,9 @@ void RegisterSecurityFilters(CoreConfiguration::Builder* builder) {
static void do_basic_init(void) {
grpc_core::InitInternally = grpc_init;
grpc_core::ShutdownInternally = grpc_shutdown;
grpc_core::IsInitializedInternally = []() {
return grpc_is_initialized() != 0;
};
gpr_log_verbosity_init();
g_init_mu = new grpc_core::Mutex();
g_shutting_down_cv = new grpc_core::CondVar();

@ -20,5 +20,6 @@ namespace grpc_core {
void (*InitInternally)();
void (*ShutdownInternally)();
bool (*IsInitializedInternally)();
} // namespace grpc_core

@ -22,6 +22,7 @@ namespace grpc_core {
// Avoids a build dependency cycle between grpc and grpc_base (and friends).
extern void (*InitInternally)();
extern void (*ShutdownInternally)();
extern bool (*IsInitializedInternally)();
class KeepsGrpcInitialized {
public:

@ -108,6 +108,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/transport/chttp2/transport/hpack_parser.cc',
'src/core/ext/transport/chttp2/transport/hpack_parser_table.cc',
'src/core/ext/transport/chttp2/transport/http2_settings.cc',
'src/core/ext/transport/chttp2/transport/http_trace.cc',
'src/core/ext/transport/chttp2/transport/huffsyms.cc',
'src/core/ext/transport/chttp2/transport/parsing.cc',
'src/core/ext/transport/chttp2/transport/stream_lists.cc',

@ -77,8 +77,8 @@
deps.append("${_gRPC_PROTOBUF_PROTOC_LIBRARIES}")
if target_dict.language == 'c++':
deps.append("${_gRPC_PROTOBUF_LIBRARIES}")
deps.append("${_gRPC_ZLIB_LIBRARIES}")
if target_dict['name'] in ['grpc', 'grpc_cronet', 'grpc_unsecure']:
deps.append("${_gRPC_ZLIB_LIBRARIES}")
deps.append("${_gRPC_CARES_LIBRARIES}")
deps.append("${_gRPC_ADDRESS_SORTING_LIBRARIES}")
deps.append("${_gRPC_RE2_LIBRARIES}")

@ -25,20 +25,14 @@ grpc_cc_library(
hdrs = ["test_wakeup_schedulers.h"],
external_deps = ["gtest"],
visibility = ["//test/core:__subpackages__"],
deps = [
"//:gpr",
],
)
grpc_cc_library(
name = "test_context",
testonly = True,
hdrs = ["test_context.h"],
external_deps = ["gtest"],
visibility = ["//test/core:__subpackages__"],
deps = [
"//:gpr",
],
deps = ["//src/core:context"],
)
grpc_cc_test(
@ -48,9 +42,7 @@ grpc_cc_test(
language = "c++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:poll",
],
deps = ["//src/core:poll"],
)
grpc_cc_test(
@ -60,9 +52,7 @@ grpc_cc_test(
language = "c++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:context",
],
deps = ["//src/core:context"],
)
grpc_cc_test(
@ -72,15 +62,16 @@ grpc_cc_test(
language = "c++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//:promise",
],
deps = ["//:promise"],
)
grpc_cc_test(
name = "arena_promise_test",
srcs = ["arena_promise_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/types:variant",
"gtest",
],
language = "c++",
tags = [
"promise_test",
@ -89,8 +80,12 @@ grpc_cc_test(
uses_event_engine = False,
uses_polling = False,
deps = [
":test_context",
"test_context",
"//:exec_ctx",
"//:ref_counted_ptr",
"//src/core:arena_promise",
"//src/core:event_engine_memory_allocator",
"//src/core:memory_quota",
"//src/core:resource_quota",
"//test/core/util:grpc_test_util_unsecure",
],
@ -123,17 +118,15 @@ grpc_cc_test(
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:race",
],
deps = ["//src/core:race"],
)
grpc_cc_test(
name = "promise_factory_test",
srcs = ["promise_factory_test.cc"],
external_deps = [
"gtest",
"absl/functional:bind_front",
"gtest",
],
language = "c++",
tags = ["promise_test"],
@ -141,6 +134,7 @@ grpc_cc_test(
uses_polling = False,
deps = [
"//:promise",
"//src/core:poll",
"//src/core:promise_factory",
],
)
@ -153,9 +147,7 @@ grpc_cc_test(
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:if",
],
deps = ["//src/core:if"],
)
grpc_cc_test(
@ -167,6 +159,7 @@ grpc_cc_test(
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:basic_seq",
"//src/core:loop",
"//src/core:seq",
],
@ -182,33 +175,36 @@ grpc_cc_test(
uses_polling = False,
deps = [
"//src/core:join",
"//src/core:poll",
],
)
grpc_cc_test(
name = "try_join_test",
srcs = ["try_join_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/utility",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:try_join",
],
deps = ["//src/core:try_join"],
)
grpc_cc_test(
name = "seq_test",
srcs = ["seq_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/types:variant",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:seq",
],
deps = ["//src/core:seq"],
)
grpc_cc_test(
@ -219,22 +215,28 @@ grpc_cc_test(
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:try_seq",
],
deps = ["//src/core:try_seq"],
)
grpc_cc_test(
name = "try_seq_metadata_test",
srcs = ["try_seq_metadata_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/types:variant",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"//:grpc",
"//:grpc_base",
"//:grpc_public_hdrs",
"//:ref_counted_ptr",
"//src/core:arena",
"//src/core:memory_quota",
"//src/core:poll",
"//src/core:resource_quota",
"//src/core:try_seq",
],
)
@ -261,13 +263,18 @@ grpc_cc_test(
grpc_cc_test(
name = "latch_test",
srcs = ["latch_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/status",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"test_wakeup_schedulers",
"//src/core:activity",
"//src/core:basic_join",
"//src/core:join",
"//src/core:latch",
"//src/core:seq",
@ -277,7 +284,10 @@ grpc_cc_test(
grpc_cc_test(
name = "observable_test",
srcs = ["observable_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/status",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
@ -300,10 +310,16 @@ grpc_cc_test(
uses_polling = False,
deps = [
"test_wakeup_schedulers",
"//:ref_counted_ptr",
"//src/core:activity",
"//src/core:arena",
"//src/core:basic_join",
"//src/core:basic_seq",
"//src/core:event_engine_memory_allocator",
"//src/core:for_each",
"//src/core:join",
"//src/core:map",
"//src/core:observable",
"//src/core:memory_quota",
"//src/core:pipe",
"//src/core:resource_quota",
"//src/core:seq",
@ -321,12 +337,19 @@ grpc_cc_test(
uses_polling = False,
deps = [
"test_wakeup_schedulers",
"//:ref_counted_ptr",
"//src/core:activity",
"//src/core:arena",
"//src/core:basic_join",
"//src/core:basic_seq",
"//src/core:event_engine_memory_allocator",
"//src/core:for_each",
"//src/core:join",
"//src/core:map",
"//src/core:map_pipe",
"//src/core:observable",
"//src/core:memory_quota",
"//src/core:pipe",
"//src/core:poll",
"//src/core:resource_quota",
"//src/core:seq",
"//src/core:try_seq",
@ -336,15 +359,24 @@ grpc_cc_test(
grpc_cc_test(
name = "pipe_test",
srcs = ["pipe_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/status",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"test_wakeup_schedulers",
"//:promise",
"//:gpr",
"//:ref_counted_ptr",
"//src/core:activity",
"//src/core:basic_join",
"//src/core:event_engine_memory_allocator",
"//src/core:join",
"//src/core:map",
"//src/core:memory_quota",
"//src/core:pipe",
"//src/core:resource_quota",
"//src/core:seq",
@ -355,25 +387,34 @@ grpc_proto_fuzzer(
name = "promise_fuzzer",
srcs = ["promise_fuzzer.cc"],
corpus = "promise_fuzzer_corpus",
external_deps = [
"absl/status",
"absl/types:optional",
],
language = "C++",
proto = "promise_fuzzer.proto",
tags = ["no_windows"],
uses_polling = False,
deps = [
"//:gpr",
"//:promise",
"//src/core:activity",
"//src/core:basic_join",
"//src/core:join",
"//src/core:map",
"//src/core:poll",
"//src/core:race",
"//src/core:seq",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "exec_ctx_wakeup_scheduler_test",
srcs = ["exec_ctx_wakeup_scheduler_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/status",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
@ -381,16 +422,14 @@ grpc_cc_test(
deps = [
"//src/core:activity",
"//src/core:exec_ctx_wakeup_scheduler",
"//src/core:poll",
],
)
grpc_cc_test(
name = "sleep_test",
srcs = ["sleep_test.cc"],
external_deps = [
"gtest",
"absl/synchronization",
],
external_deps = ["gtest"],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
@ -399,7 +438,10 @@ grpc_cc_test(
"test_wakeup_schedulers",
"//:exec_ctx",
"//:grpc",
"//src/core:activity",
"//src/core:default_event_engine",
"//src/core:exec_ctx_wakeup_scheduler",
"//src/core:notification",
"//src/core:race",
"//src/core:sleep",
"//test/core/event_engine:mock_event_engine",
],
@ -409,14 +451,13 @@ grpc_cc_test(
name = "try_concurrently_test",
srcs = ["try_concurrently_test.cc"],
external_deps = [
"gtest",
"absl/status",
"absl/strings",
"gtest",
],
language = "c++",
tags = ["promise_test"],
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:try_concurrently",
],
deps = ["//src/core:try_concurrently"],
)

@ -0,0 +1,78 @@
# Copyright 2021 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
licenses(["notice"])
grpc_package(
name = "test/core/transport/chaotic_good",
visibility = "tests",
)
grpc_cc_test(
name = "frame_header_test",
srcs = ["frame_header_test.cc"],
external_deps = [
"absl/status",
"gtest",
],
deps = ["//src/core:chaotic_good_frame_header"],
)
grpc_fuzzer(
name = "frame_header_fuzzer",
srcs = ["frame_header_fuzzer.cc"],
corpus = "frame_header_fuzzer_corpus",
external_deps = ["absl/status:statusor"],
language = "C++",
tags = ["no_windows"],
deps = ["//src/core:chaotic_good_frame_header"],
)
grpc_cc_test(
name = "frame_test",
srcs = ["frame_test.cc"],
external_deps = [
"absl/status",
"absl/status:statusor",
"gtest",
],
deps = ["//src/core:chaotic_good_frame"],
)
grpc_fuzzer(
name = "frame_fuzzer",
srcs = ["frame_fuzzer.cc"],
corpus = "frame_fuzzer_corpus",
external_deps = ["absl/status:statusor"],
language = "C++",
tags = ["no_windows"],
deps = [
"//:gpr",
"//:hpack_encoder",
"//:hpack_parser",
"//:ref_counted_ptr",
"//src/core:arena",
"//src/core:chaotic_good_frame",
"//src/core:chaotic_good_frame_header",
"//src/core:event_engine_memory_allocator",
"//src/core:memory_quota",
"//src/core:resource_quota",
"//src/core:slice",
"//src/core:slice_buffer",
"//test/core/promise:test_context",
],
)

@ -0,0 +1,112 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "absl/status/statusor.h"
#include <grpc/event_engine/memory_allocator.h>
#include <grpc/support/log.h>
#include "src/core/ext/transport/chaotic_good/frame.h"
#include "src/core/ext/transport/chaotic_good/frame_header.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/resource_quota/memory_quota.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "test/core/promise/test_context.h"
bool squelch = false;
namespace grpc_core {
namespace chaotic_good {
static auto* g_memory_allocator = new MemoryAllocator(
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
template <typename T>
void AssertRoundTrips(const T& input, FrameType expected_frame_type) {
HPackCompressor hpack_compressor;
auto serialized = input.Serialize(&hpack_compressor);
GPR_ASSERT(serialized.Length() >= 64);
GPR_ASSERT(serialized.Length() % 64 == 0);
uint8_t header_bytes[64];
serialized.MoveFirstNBytesIntoBuffer(64, header_bytes);
auto header = FrameHeader::Parse(header_bytes);
GPR_ASSERT(header.ok());
GPR_ASSERT(header->type == expected_frame_type);
T output;
HPackParser hpack_parser;
auto deser = output.Deserialize(&hpack_parser, header.value(), serialized);
GPR_ASSERT(deser.ok());
GPR_ASSERT(output == input);
}
template <typename T>
void FinishParseAndChecks(const FrameHeader& header, const uint8_t* data,
size_t size) {
T parsed;
HPackParser hpack_parser;
SliceBuffer serialized;
serialized.Append(Slice::FromCopiedBuffer(data, size));
auto deser = parsed.Deserialize(&hpack_parser, header, serialized);
if (!deser.ok()) return;
AssertRoundTrips(parsed, header.type);
}
int Run(const uint8_t* data, size_t size) {
if (size < 1) return 0;
const bool is_server = (data[0] & 1) != 0;
size--;
data++;
if (size < 64) return 0;
auto r = FrameHeader::Parse(data);
if (!r.ok()) return 0;
size -= 64;
data += 64;
auto arena = MakeScopedArena(1024, g_memory_allocator);
TestContext<Arena> ctx(arena.get());
switch (r->type) {
default:
return 0; // We don't know how to parse this frame type.
case FrameType::kSettings:
FinishParseAndChecks<SettingsFrame>(*r, data, size);
break;
case FrameType::kFragment:
if (is_server) {
FinishParseAndChecks<ServerFragmentFrame>(*r, data, size);
} else {
FinishParseAndChecks<ClientFragmentFrame>(*r, data, size);
}
break;
case FrameType::kCancel:
FinishParseAndChecks<CancelFrame>(*r, data, size);
break;
}
return 0;
}
} // namespace chaotic_good
} // namespace grpc_core
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return grpc_core::chaotic_good::Run(data, size);
}

@ -0,0 +1,34 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "absl/status/statusor.h"
#include "src/core/ext/transport/chaotic_good/frame_header.h"
bool squelch = false;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size != 64) return 0;
auto r = grpc_core::chaotic_good::FrameHeader::Parse(data);
if (!r.ok()) return 0;
uint8_t reserialized[64];
r->Serialize(reserialized);
// If it parses, we insist that the bytes reserialize to the same thing.
if (memcmp(data, reserialized, 64) != 0) abort();
return 0;
}

@ -0,0 +1,120 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/core/ext/transport/chaotic_good/frame_header.h"
#include <algorithm>
#include <cstdint>
#include <vector>
#include "absl/status/status.h"
#include "gtest/gtest.h"
namespace grpc_core {
namespace chaotic_good {
namespace {
std::vector<uint8_t> Serialize(FrameHeader h) {
uint8_t buffer[64];
h.Serialize(buffer);
return std::vector<uint8_t>(buffer, buffer + 64);
}
absl::StatusOr<FrameHeader> Deserialize(std::vector<uint8_t> data) {
if (data.size() != 64) return absl::InvalidArgumentError("bad length");
return FrameHeader::Parse(data.data());
}
TEST(FrameHeaderTest, SimpleSerialize) {
EXPECT_EQ(
Serialize(FrameHeader{FrameType::kCancel, BitSet<3>::FromInt(0),
0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10}),
std::vector<uint8_t>({0x81, 0, 0, 0, // type, flags
0x04, 0x03, 0x02, 0x01, // stream_id
0x08, 0x07, 0x06, 0x05, // header_length
0x0c, 0x0b, 0x0a, 0x09, // message_length
0x10, 0x0f, 0x0e, 0x0d, // trailer_length
// padding
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
}
TEST(FrameHeaderTest, SimpleDeserialize) {
EXPECT_EQ(
Deserialize(std::vector<uint8_t>(
{0x81, 0, 0, 0, // type, flags
0x04, 0x03, 0x02, 0x01, // stream_id
0x08, 0x07, 0x06, 0x05, // header_length
0x0c, 0x0b, 0x0a, 0x09, // message_length
0x10, 0x0f, 0x0e, 0x0d, // trailer_length
// padding
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})),
absl::StatusOr<FrameHeader>(
FrameHeader{FrameType::kCancel, BitSet<3>::FromInt(0), 0x01020304,
0x05060708, 0x090a0b0c, 0x0d0e0f10}));
EXPECT_EQ(Deserialize(std::vector<uint8_t>(
{0x81, 88, 88, 88, // type, flags
0x04, 0x03, 0x02, 0x01, // stream_id
0x08, 0x07, 0x06, 0x05, // header_length
0x0c, 0x0b, 0x0a, 0x09, // message_length
0x10, 0x0f, 0x0e, 0x0d, // trailer_length
// garbage padding
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0}))
.status(),
absl::InvalidArgumentError("Invalid flags"));
EXPECT_EQ(Deserialize(std::vector<uint8_t>(
{0x81, 0, 0, 0, // type, flags
0x04, 0x03, 0x02, 0x01, // stream_id
0x08, 0x07, 0x06, 0x05, // header_length
0x0c, 0x0b, 0x0a, 0x09, // message_length
0x10, 0x0f, 0x0e, 0x0d, // trailer_length
// garbage padding
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0}))
.status(),
absl::InvalidArgumentError("Invalid padding"));
}
TEST(FrameHeaderTest, ComputeFrameSizes) {
EXPECT_EQ(
(FrameHeader{FrameType::kFragment, BitSet<3>::FromInt(7), 1, 0, 0, 0})
.ComputeFrameSizes(),
(FrameSizes{0, 0, 0}));
EXPECT_EQ(
(FrameHeader{FrameType::kFragment, BitSet<3>::FromInt(7), 1, 14, 0, 0})
.ComputeFrameSizes(),
(FrameSizes{64, 64, 64}));
EXPECT_EQ(
(FrameHeader{FrameType::kFragment, BitSet<3>::FromInt(7), 1, 0, 14, 0})
.ComputeFrameSizes(),
(FrameSizes{0, 64, 64}));
EXPECT_EQ(
(FrameHeader{FrameType::kFragment, BitSet<3>::FromInt(7), 1, 0, 0, 14})
.ComputeFrameSizes(),
(FrameSizes{0, 0, 64}));
}
} // namespace
} // namespace chaotic_good
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -0,0 +1,57 @@
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/core/ext/transport/chaotic_good/frame.h"
#include <cstdint>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "gtest/gtest.h"
namespace grpc_core {
namespace chaotic_good {
namespace {
template <typename T>
void AssertRoundTrips(const T input, FrameType expected_frame_type) {
HPackCompressor hpack_compressor;
auto serialized = input.Serialize(&hpack_compressor);
EXPECT_GE(serialized.Length(), 64);
EXPECT_EQ(serialized.Length() % 64, 0);
uint8_t header_bytes[64];
serialized.MoveFirstNBytesIntoBuffer(64, header_bytes);
auto header = FrameHeader::Parse(header_bytes);
EXPECT_TRUE(header.ok()) << header.status();
EXPECT_EQ(header->type, expected_frame_type);
T output;
HPackParser hpack_parser;
auto deser = output.Deserialize(&hpack_parser, header.value(), serialized);
EXPECT_TRUE(deser.ok()) << deser;
EXPECT_EQ(output, input);
}
TEST(FrameTest, SettingsFrameRoundTrips) {
AssertRoundTrips(SettingsFrame{}, FrameType::kSettings);
}
} // namespace
} // namespace chaotic_good
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
int r = RUN_ALL_TESTS();
return r;
}

@ -409,7 +409,9 @@ for dirname in [
"test/core/util",
"test/core/end2end",
"test/core/event_engine",
"test/core/promise",
"test/core/resource_quota",
"test/core/transport/chaotic_good",
]:
parsing_path = dirname
exec(

@ -1269,6 +1269,8 @@ src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
src/core/ext/transport/chttp2/transport/hpack_parser_table.h \
src/core/ext/transport/chttp2/transport/http2_settings.cc \
src/core/ext/transport/chttp2/transport/http2_settings.h \
src/core/ext/transport/chttp2/transport/http_trace.cc \
src/core/ext/transport/chttp2/transport/http_trace.h \
src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/huffsyms.h \
src/core/ext/transport/chttp2/transport/internal.h \

@ -1051,6 +1051,8 @@ src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
src/core/ext/transport/chttp2/transport/hpack_parser_table.h \
src/core/ext/transport/chttp2/transport/http2_settings.cc \
src/core/ext/transport/chttp2/transport/http2_settings.h \
src/core/ext/transport/chttp2/transport/http_trace.cc \
src/core/ext/transport/chttp2/transport/http_trace.h \
src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/huffsyms.h \
src/core/ext/transport/chttp2/transport/internal.h \

@ -3179,6 +3179,54 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "frame_header_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "frame_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save