Merge branch 'master' into regex_test_core_iomgr_transport

pull/36595/head
tanvi-jagtap 7 months ago
commit b0836fda1c
  1. 69
      BUILD
  2. 3
      CMakeLists.txt
  3. 1
      Makefile
  4. 3
      Package.swift
  5. 21
      bazel/experiments.bzl
  6. 9
      build_autogenerated.yaml
  7. 1
      config.m4
  8. 1
      config.w32
  9. 12
      examples/cpp/otel/BUILD
  10. 9
      examples/cpp/otel/CMakeLists.txt
  11. 6
      examples/cpp/otel/greeter_callback_client.cc
  12. 6
      examples/cpp/otel/greeter_callback_server.cc
  13. 50
      examples/cpp/otel/util.cc
  14. 31
      examples/cpp/otel/util.h
  15. 4
      gRPC-C++.podspec
  16. 5
      gRPC-Core.podspec
  17. 3
      grpc.gemspec
  18. 24
      include/grpcpp/ext/otel_plugin.h
  19. 3
      package.xml
  20. 133
      src/core/BUILD
  21. 8
      src/core/channelz/channelz.h
  22. 4
      src/core/ext/filters/logging/logging_filter.cc
  23. 76
      src/core/ext/transport/chaotic_good/server_transport.cc
  24. 12
      src/core/ext/transport/chaotic_good/server_transport.h
  25. 1
      src/core/ext/transport/cronet/BUILD
  26. 51
      src/core/ext/transport/inproc/inproc_transport.cc
  27. 2
      src/core/ext/transport/inproc/inproc_transport.h
  28. 26
      src/core/lib/channel/channel_stack.cc
  29. 1
      src/core/lib/channel/channel_stack.h
  30. 48
      src/core/lib/experiments/experiments.cc
  31. 8
      src/core/lib/experiments/experiments.h
  32. 11
      src/core/lib/experiments/experiments.yaml
  33. 2
      src/core/lib/experiments/rollouts.yaml
  34. 11
      src/core/lib/promise/detail/promise_like.h
  35. 2
      src/core/lib/promise/status_flag.h
  36. 1014
      src/core/lib/surface/call.cc
  37. 60
      src/core/lib/surface/call.h
  38. 84
      src/core/lib/surface/channel_init.cc
  39. 116
      src/core/lib/surface/channel_init.h
  40. 4
      src/core/lib/surface/init.cc
  41. 18
      src/core/lib/transport/call_destination.h
  42. 44
      src/core/lib/transport/call_filters.h
  43. 8
      src/core/lib/transport/call_spine.h
  44. 11
      src/core/lib/transport/interception_chain.h
  45. 67
      src/core/lib/transport/transport.h
  46. 3
      src/core/plugin_registry/grpc_plugin_registry.cc
  47. 632
      src/core/server/server.cc
  48. 33
      src/core/server/server.h
  49. 2
      src/core/server/server_interface.h
  50. 116
      src/core/tsi/ssl_transport_security.cc
  51. 1
      src/cpp/ext/csm/BUILD
  52. 2
      src/cpp/ext/gcp/BUILD
  53. 1
      src/python/grpcio/grpc_core_dependencies.py
  54. 418
      test/core/channelz/channel_trace_test.cc
  55. 3
      test/core/end2end/tests/filter_context.cc
  56. 33
      test/core/surface/channel_init_test.cc
  57. 6
      test/core/transport/chaotic_good/chaotic_good_server_test.cc
  58. 37
      test/core/transport/chaotic_good/server_transport_test.cc
  59. 2
      test/core/transport/test_suite/call_content.cc
  60. 18
      test/core/transport/test_suite/call_shapes.cc
  61. 6
      test/core/transport/test_suite/inproc_fixture.cc
  62. 4
      test/core/transport/test_suite/no_op.cc
  63. 2
      test/core/transport/test_suite/stress.cc
  64. 29
      test/core/transport/test_suite/test.cc
  65. 17
      test/core/transport/test_suite/test.h
  66. 1
      test/core/tsi/BUILD
  67. 1
      test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong_chaotic_good.cc
  68. 37
      test/cpp/util/channel_trace_proto_helper.cc
  69. 22
      test/cpp/util/channel_trace_proto_helper.h
  70. 3
      tools/doxygen/Doxyfile.c++.internal
  71. 3
      tools/doxygen/Doxyfile.core.internal

69
BUILD

@ -583,6 +583,7 @@ grpc_cc_library(
defines = ["GRPC_NO_XDS"],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
],
language = "c++",
public_hdrs = GRPC_PUBLIC_HDRS,
@ -654,6 +655,7 @@ grpc_cc_library(
}),
external_deps = [
"absl/base:core_headers",
"absl/log:log",
],
language = "c++",
public_hdrs = GRPC_PUBLIC_HDRS,
@ -787,9 +789,9 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/base:log_severity",
"absl/functional:any_invocable",
"absl/log",
"absl/log:check",
"absl/log:globals",
"absl/log:log",
"absl/memory",
"absl/random",
"absl/status",
@ -906,6 +908,7 @@ grpc_cc_library(
hdrs = GRPCXX_PUBLIC_HDRS,
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:cord",
"absl/synchronization",
"protobuf_headers",
@ -936,6 +939,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:cord",
],
language = "c++",
@ -1005,6 +1009,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -1064,6 +1069,7 @@ grpc_cc_library(
],
external_deps = [
"absl/container:flat_hash_set",
"absl/log:log",
"absl/strings",
"absl/types:optional",
"absl/types:span",
@ -1250,6 +1256,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/synchronization",
],
@ -1300,6 +1307,7 @@ grpc_cc_library(
"include/grpcpp/security/alts_util.h",
],
external_deps = [
"absl/log:log",
"@com_google_protobuf//upb:base",
"@com_google_protobuf//upb:mem",
"@com_google_protobuf//upb:message",
@ -1382,6 +1390,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -1441,6 +1450,7 @@ grpc_cc_library(
external_deps = [
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
],
language = "c++",
deps = [
@ -1492,6 +1502,9 @@ grpc_cc_library(
hdrs = [
"//src/core:lib/surface/api_trace.h",
],
external_deps = [
"absl/log:log",
],
language = "c++",
deps = [
"gpr",
@ -1810,6 +1823,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",
@ -1899,6 +1913,7 @@ grpc_cc_library(
"absl/container:flat_hash_set",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/status",
"absl/status:statusor",
@ -1928,9 +1943,7 @@ grpc_cc_library(
"promise",
"ref_counted_ptr",
"stats",
"//src/core:1999",
"//src/core:activity",
"//src/core:arena",
"//src/core:arena_promise",
"//src/core:cancel_callback",
"//src/core:channel_args",
@ -1944,6 +1957,7 @@ grpc_cc_library(
"//src/core:error",
"//src/core:error_utils",
"//src/core:experiments",
"//src/core:interception_chain",
"//src/core:iomgr_fwd",
"//src/core:map",
"//src/core:metadata_batch",
@ -2064,6 +2078,7 @@ grpc_cc_library(
"//src/core:arena_promise",
"//src/core:atomic_utils",
"//src/core:bitset",
"//src/core:call_destination",
"//src/core:call_filters",
"//src/core:call_final_info",
"//src/core:call_finalization",
@ -2145,6 +2160,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
deps = [
@ -2177,6 +2193,9 @@ grpc_cc_library(
"src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc",
"src/cpp/server/load_reporter/util.cc",
],
external_deps = [
"absl/log:log",
],
language = "c++",
public_hdrs = [
"include/grpcpp/ext/server_load_reporting.h",
@ -2205,6 +2224,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/memory",
"protobuf_headers",
],
@ -2229,6 +2249,9 @@ grpc_cc_library(
hdrs = [
"src/cpp/server/load_reporter/get_cpu_stats.h",
],
external_deps = [
"absl/log:log",
],
language = "c++",
deps = [
"gpr",
@ -2247,6 +2270,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"opencensus-stats",
"opencensus-tags",
"protobuf_headers",
@ -2292,6 +2316,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2399,6 +2424,7 @@ grpc_cc_library(
"//src/core:tsi/alts/handshaker/transport_security_common_api.h",
],
external_deps = [
"absl/log:log",
"@com_google_protobuf//upb:base",
"@com_google_protobuf//upb:mem",
],
@ -2457,6 +2483,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2541,6 +2568,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2974,6 +3002,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
],
language = "c++",
visibility = ["@grpc:client_channel"],
@ -2994,7 +3023,10 @@ grpc_cc_library(
name = "grpc_trace",
srcs = ["//src/core:lib/debug/trace.cc"],
hdrs = ["//src/core:lib/debug/trace.h"],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
visibility = ["@grpc:trace"],
deps = [
@ -3139,6 +3171,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -3175,6 +3208,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -3221,6 +3255,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:str_format",
],
visibility = [
@ -3252,6 +3287,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3286,6 +3322,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
],
@ -3314,6 +3351,9 @@ grpc_cc_library(
hdrs = [
"//src/core:lib/iomgr/internal_errqueue.h",
],
external_deps = [
"absl/log:log",
],
tags = ["nofixdeps"],
visibility = ["@grpc:iomgr_internal_errqueue"],
deps = [
@ -3332,6 +3372,7 @@ grpc_cc_library(
"//src/core:lib/iomgr/buffer_list.h",
],
external_deps = [
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
"absl/types:optional",
@ -3378,6 +3419,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3545,6 +3587,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3578,6 +3621,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"@com_google_protobuf//upb:base",
@ -3620,6 +3664,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -3811,6 +3856,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3875,6 +3921,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:bind_front",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3929,6 +3976,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -3973,6 +4021,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
visibility = [
@ -4061,7 +4110,10 @@ grpc_cc_library(
"//src/core:lib/security/security_connector/load_system_roots_supported.h",
"//src/core:lib/security/util/json_util.h",
],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
visibility = ["@grpc:public"],
deps = [
@ -4154,6 +4206,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/types:span",
"libcrypto",
"libssl",
@ -4185,6 +4238,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/memory",
"libssl",
],
@ -4265,6 +4319,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4517,6 +4572,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -4573,6 +4629,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/random:bit_gen_ref",
"absl/status",
"absl/strings",
@ -4615,6 +4672,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
deps = [
@ -4855,6 +4913,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/types:span",
],

3
CMakeLists.txt generated

@ -2502,6 +2502,7 @@ add_library(grpc
src/core/lib/transport/call_spine.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/interception_chain.cc
src/core/lib/transport/message.cc
src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc
@ -3255,6 +3256,7 @@ add_library(grpc_unsecure
src/core/lib/transport/call_spine.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/interception_chain.cc
src/core/lib/transport/message.cc
src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc
@ -5366,6 +5368,7 @@ add_library(grpc_authorization_provider
src/core/lib/transport/call_spine.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/interception_chain.cc
src/core/lib/transport/message.cc
src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc

1
Makefile generated

@ -1387,6 +1387,7 @@ LIBGRPC_SRC = \
src/core/lib/transport/call_spine.cc \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/interception_chain.cc \
src/core/lib/transport/message.cc \
src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \

3
Package.swift generated

@ -1749,6 +1749,7 @@ let package = Package(
"src/core/lib/transport/bdp_estimator.h",
"src/core/lib/transport/call_arena_allocator.cc",
"src/core/lib/transport/call_arena_allocator.h",
"src/core/lib/transport/call_destination.h",
"src/core/lib/transport/call_filters.cc",
"src/core/lib/transport/call_filters.h",
"src/core/lib/transport/call_final_info.cc",
@ -1761,6 +1762,8 @@ let package = Package(
"src/core/lib/transport/error_utils.cc",
"src/core/lib/transport/error_utils.h",
"src/core/lib/transport/http2_errors.h",
"src/core/lib/transport/interception_chain.cc",
"src/core/lib/transport/interception_chain.h",
"src/core/lib/transport/message.cc",
"src/core/lib/transport/message.h",
"src/core/lib/transport/metadata.cc",

@ -34,9 +34,8 @@ EXPERIMENT_ENABLES = {
"pending_queue_cap": "pending_queue_cap",
"pick_first_new": "pick_first_new",
"promise_based_client_call": "event_engine_client,event_engine_listener,promise_based_client_call",
"promise_based_server_call": "promise_based_server_call",
"chaotic_good": "chaotic_good,event_engine_client,event_engine_listener,promise_based_client_call,promise_based_server_call",
"promise_based_inproc_transport": "event_engine_client,event_engine_listener,promise_based_client_call,promise_based_inproc_transport,promise_based_server_call",
"chaotic_good": "chaotic_good,event_engine_client,event_engine_listener,promise_based_client_call",
"promise_based_inproc_transport": "event_engine_client,event_engine_listener,promise_based_client_call,promise_based_inproc_transport",
"rstpit": "rstpit",
"schedule_cancellation_over_write": "schedule_cancellation_over_write",
"server_privacy": "server_privacy",
@ -59,9 +58,6 @@ EXPERIMENTS = {
"dbg": {
},
"off": {
"core_end2end_test": [
"promise_based_server_call",
],
"endpoint_test": [
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
@ -73,9 +69,6 @@ EXPERIMENTS = {
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],
"logging_test": [
"promise_based_server_call",
],
"resource_quota_test": [
"free_large_allocator",
"unconstrained_max_quota_buffer_size",
@ -107,9 +100,6 @@ EXPERIMENTS = {
"dbg": {
},
"off": {
"core_end2end_test": [
"promise_based_server_call",
],
"endpoint_test": [
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
@ -121,9 +111,6 @@ EXPERIMENTS = {
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],
"logging_test": [
"promise_based_server_call",
],
"resource_quota_test": [
"free_large_allocator",
"unconstrained_max_quota_buffer_size",
@ -149,7 +136,6 @@ EXPERIMENTS = {
"chaotic_good",
"event_engine_client",
"promise_based_client_call",
"promise_based_server_call",
],
"endpoint_test": [
"tcp_frame_size_tuning",
@ -168,9 +154,6 @@ EXPERIMENTS = {
"lame_client_test": [
"promise_based_client_call",
],
"logging_test": [
"promise_based_server_call",
],
"resource_quota_test": [
"free_large_allocator",
"unconstrained_max_quota_buffer_size",

@ -1110,6 +1110,7 @@ libs:
- src/core/lib/transport/batch_builder.h
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/call_arena_allocator.h
- src/core/lib/transport/call_destination.h
- src/core/lib/transport/call_filters.h
- src/core/lib/transport/call_final_info.h
- src/core/lib/transport/call_spine.h
@ -1117,6 +1118,7 @@ libs:
- src/core/lib/transport/custom_metadata.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/interception_chain.h
- src/core/lib/transport/message.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
@ -1921,6 +1923,7 @@ libs:
- src/core/lib/transport/call_spine.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/interception_chain.cc
- src/core/lib/transport/message.cc
- src/core/lib/transport/metadata.cc
- src/core/lib/transport/metadata_batch.cc
@ -2609,6 +2612,7 @@ libs:
- src/core/lib/transport/batch_builder.h
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/call_arena_allocator.h
- src/core/lib/transport/call_destination.h
- src/core/lib/transport/call_filters.h
- src/core/lib/transport/call_final_info.h
- src/core/lib/transport/call_spine.h
@ -2616,6 +2620,7 @@ libs:
- src/core/lib/transport/custom_metadata.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/interception_chain.h
- src/core/lib/transport/message.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
@ -3032,6 +3037,7 @@ libs:
- src/core/lib/transport/call_spine.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/interception_chain.cc
- src/core/lib/transport/message.cc
- src/core/lib/transport/metadata.cc
- src/core/lib/transport/metadata_batch.cc
@ -4686,6 +4692,7 @@ libs:
- src/core/lib/surface/wait_for_cq_end_op.h
- src/core/lib/transport/batch_builder.h
- src/core/lib/transport/call_arena_allocator.h
- src/core/lib/transport/call_destination.h
- src/core/lib/transport/call_filters.h
- src/core/lib/transport/call_final_info.h
- src/core/lib/transport/call_spine.h
@ -4693,6 +4700,7 @@ libs:
- src/core/lib/transport/custom_metadata.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/interception_chain.h
- src/core/lib/transport/message.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
@ -4989,6 +4997,7 @@ libs:
- src/core/lib/transport/call_spine.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/interception_chain.cc
- src/core/lib/transport/message.cc
- src/core/lib/transport/metadata.cc
- src/core/lib/transport/metadata_batch.cc

1
config.m4 generated

@ -762,6 +762,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/transport/call_spine.cc \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/interception_chain.cc \
src/core/lib/transport/message.cc \
src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \

1
config.w32 generated

@ -727,6 +727,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\transport\\call_spine.cc " +
"src\\core\\lib\\transport\\connectivity_state.cc " +
"src\\core\\lib\\transport\\error_utils.cc " +
"src\\core\\lib\\transport\\interception_chain.cc " +
"src\\core\\lib\\transport\\message.cc " +
"src\\core\\lib\\transport\\metadata.cc " +
"src\\core\\lib\\transport\\metadata_batch.cc " +

@ -14,11 +14,22 @@
licenses(["notice"])
cc_library(
name = "util",
srcs = ["util.cc"],
hdrs = ["util.h"],
deps = [
"//:grpc++",
"@io_opentelemetry_cpp//sdk/src/metrics",
],
)
cc_binary(
name = "greeter_callback_client",
srcs = ["greeter_callback_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"util",
"//:grpc++",
"//:grpcpp_otel_plugin",
"//examples/protos:helloworld_cc_grpc",
@ -34,6 +45,7 @@ cc_binary(
srcs = ["greeter_callback_server.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"util",
"//:grpc++",
"//:grpc++_reflection",
"//:grpcpp_otel_plugin",

@ -50,6 +50,7 @@ add_custom_command(
# Include generated *.pb.h files
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories("${CMAKE_SOURCE_DIR}")
# hw_grpc_proto
add_library(hw_grpc_proto
@ -62,6 +63,13 @@ target_link_libraries(hw_grpc_proto
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})
# util
add_library(util
"util.cc")
target_link_libraries(util
opentelemetry-cpp::metrics
${_GRPC_GRPCPP})
# Targets greeter_callback_(client|server)
foreach(_target
greeter_callback_client greeter_callback_server)
@ -75,5 +83,6 @@ foreach(_target
${_REFLECTION}
${_GRPC_GRPCPP}
gRPC::grpcpp_otel_plugin
util
${_PROTOBUF_LIBPROTOBUF})
endforeach()

@ -33,9 +33,11 @@
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/util.h"
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#include "util.h"
#endif
ABSL_FLAG(std::string, target, "localhost:50051", "Server address");
@ -110,6 +112,10 @@ int main(int argc, char** argv) {
opentelemetry::exporter::metrics::PrometheusExporterFactory::Create(opts);
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
// The default histogram boundaries are not granular enough for RPCs. Override
// the "grpc.client.attempt.duration" view as recommended by
// https://github.com/grpc/proposal/blob/master/A66-otel-stats.md.
AddLatencyView(meter_provider.get(), "grpc.client.attempt.duration", "s");
meter_provider->AddMetricReader(std::move(prometheus_exporter));
auto status = grpc::OpenTelemetryPluginBuilder()
.SetMeterProvider(std::move(meter_provider))

@ -33,9 +33,11 @@
#include <grpcpp/health_check_service_interface.h>
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/util.h"
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#include "util.h"
#endif
ABSL_FLAG(uint16_t, port, 50051, "Server port for the service");
@ -96,6 +98,10 @@ int main(int argc, char** argv) {
opentelemetry::exporter::metrics::PrometheusExporterFactory::Create(opts);
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
// The default histogram boundaries are not granular enough for RPCs. Override
// the "grpc.server.call.duration" view as recommended by
// https://github.com/grpc/proposal/blob/master/A66-otel-stats.md.
AddLatencyView(meter_provider.get(), "grpc.server.call.duration", "s");
meter_provider->AddMetricReader(std::move(prometheus_exporter));
auto status = grpc::OpenTelemetryPluginBuilder()
.SetMeterProvider(std::move(meter_provider))

@ -0,0 +1,50 @@
//
//
// Copyright 2024 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.
//
//
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/util.h"
#else
#include "util.h"
#endif
#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h"
#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h"
#include "opentelemetry/sdk/metrics/view/view_factory.h"
#include <grpcpp/grpcpp.h>
void AddLatencyView(opentelemetry::sdk::metrics::MeterProvider* provider,
const std::string& name, const std::string& unit) {
auto histogram_config = std::make_shared<
opentelemetry::sdk::metrics::HistogramAggregationConfig>();
histogram_config->boundaries_ = {
0, 0.00001, 0.00005, 0.0001, 0.0003, 0.0006, 0.0008, 0.001, 0.002,
0.003, 0.004, 0.005, 0.006, 0.008, 0.01, 0.013, 0.016, 0.02,
0.025, 0.03, 0.04, 0.05, 0.065, 0.08, 0.1, 0.13, 0.16,
0.2, 0.25, 0.3, 0.4, 0.5, 0.65, 0.8, 1, 2,
5, 10, 20, 50, 100};
provider->AddView(
opentelemetry::sdk::metrics::InstrumentSelectorFactory::Create(
opentelemetry::sdk::metrics::InstrumentType::kHistogram, name, unit),
opentelemetry::sdk::metrics::MeterSelectorFactory::Create(
"grpc-c++", grpc::Version(), ""),
opentelemetry::sdk::metrics::ViewFactory::Create(
name, "", unit,
opentelemetry::sdk::metrics::AggregationType::kHistogram,
std::move(histogram_config)));
}

@ -0,0 +1,31 @@
//
//
// Copyright 2024 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 GRPCPP_EXAMPLES_CPP_OTEL_UTIL_H
#define GRPCPP_EXAMPLES_CPP_OTEL_UTIL_H
#include <string>
#include "opentelemetry/sdk/metrics/meter_provider.h"
// Helper function that adds view for gRPC latency instrument \a name with unit
// \a unit with bucket boundaries that are more useful for RPCs.
void AddLatencyView(opentelemetry::sdk::metrics::MeterProvider* provider,
const std::string& name, const std::string& unit);
#endif // GRPCPP_EXAMPLES_CPP_OTEL_UTIL_H

4
gRPC-C++.podspec generated

@ -1213,6 +1213,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/batch_builder.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.h',
'src/core/lib/transport/call_spine.h',
@ -1220,6 +1221,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/custom_metadata.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',
@ -2482,6 +2484,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/batch_builder.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.h',
'src/core/lib/transport/call_spine.h',
@ -2489,6 +2492,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/custom_metadata.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',

5
gRPC-Core.podspec generated

@ -1864,6 +1864,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.cc',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.cc',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.cc',
@ -1876,6 +1877,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/error_utils.cc',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.cc',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.cc',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.cc',
@ -3261,6 +3264,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/batch_builder.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.h',
'src/core/lib/transport/call_spine.h',
@ -3268,6 +3272,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/custom_metadata.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',

3
grpc.gemspec generated

@ -1751,6 +1751,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/bdp_estimator.h )
s.files += %w( src/core/lib/transport/call_arena_allocator.cc )
s.files += %w( src/core/lib/transport/call_arena_allocator.h )
s.files += %w( src/core/lib/transport/call_destination.h )
s.files += %w( src/core/lib/transport/call_filters.cc )
s.files += %w( src/core/lib/transport/call_filters.h )
s.files += %w( src/core/lib/transport/call_final_info.cc )
@ -1763,6 +1764,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/error_utils.cc )
s.files += %w( src/core/lib/transport/error_utils.h )
s.files += %w( src/core/lib/transport/http2_errors.h )
s.files += %w( src/core/lib/transport/interception_chain.cc )
s.files += %w( src/core/lib/transport/interception_chain.h )
s.files += %w( src/core/lib/transport/message.cc )
s.files += %w( src/core/lib/transport/message.h )
s.files += %w( src/core/lib/transport/metadata.cc )

@ -88,11 +88,25 @@ class OpenTelemetryPluginBuilder {
/// If `SetMeterProvider()` is not called, no metrics are collected.
OpenTelemetryPluginBuilder& SetMeterProvider(
std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider);
/// If set, \a target_attribute_filter is called per channel to decide whether
/// to record the target attribute on client or to replace it with "other".
/// This helps reduce the cardinality on metrics in cases where many channels
/// are created with different targets in the same binary (which might happen
/// for example, if the channel target string uses IP addresses directly).
/// DEPRECATED: If set, \a target_attribute_filter is called per channel to
/// decide whether to record the target attribute on client or to replace it
/// with "other". This helps reduce the cardinality on metrics in cases where
/// many channels are created with different targets in the same binary (which
/// might happen for example, if the channel target string uses IP addresses
/// directly).
/// This filtration only works for the per-call metrics -
/// grpc.client.attempt.started
/// grpc.client.attempt.duration
/// grpc.client.attempt.sent_total_compressed_message_size
/// grpc.client.attempt.rcvd_total_compressed_message_size
/// For example, the grpc.target attribute on pick first lb policy metrics
/// defined in
/// https://github.com/grpc/proposal/blob/master/A78-grpc-metrics-wrr-pf-xds.md
/// will not be filtered. Please contact the grpc team if this filtration is
/// of interest to you.
GRPC_DEPRECATED(
"Does not work as expected. Please raise an issue on "
"https://github.com/grpc/grpc if this would be of use to you.")
OpenTelemetryPluginBuilder& SetTargetAttributeFilter(
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter);

3
package.xml generated

@ -1733,6 +1733,7 @@
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_arena_allocator.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_arena_allocator.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_destination.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_filters.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_filters.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_final_info.cc" role="src" />
@ -1745,6 +1746,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/http2_errors.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/interception_chain.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/interception_chain.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/message.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/message.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.cc" role="src" />

@ -216,6 +216,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -414,6 +415,7 @@ grpc_cc_library(
"lib/gprpp/validation_errors.h",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -530,7 +532,10 @@ grpc_cc_library(
grpc_cc_library(
name = "map_pipe",
external_deps = ["absl/status"],
external_deps = [
"absl/log:log",
"absl/status",
],
language = "c++",
public_hdrs = [
"lib/promise/map_pipe.h",
@ -559,6 +564,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
],
@ -658,7 +664,10 @@ grpc_cc_library(
grpc_cc_library(
name = "promise_like",
external_deps = ["absl/meta:type_traits"],
external_deps = [
"absl/functional:any_invocable",
"absl/meta:type_traits",
],
language = "c++",
public_hdrs = [
"lib/promise/detail/promise_like.h",
@ -1003,6 +1012,7 @@ grpc_cc_library(
name = "latch",
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -1021,6 +1031,7 @@ grpc_cc_library(
name = "inter_activity_latch",
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -1043,6 +1054,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
"absl/types:optional",
@ -1066,6 +1078,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/types:optional",
"absl/types:variant",
@ -1177,6 +1190,7 @@ grpc_cc_library(
name = "for_each",
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -1199,6 +1213,7 @@ grpc_cc_library(
name = "ref_counted",
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
public_hdrs = ["lib/gprpp/ref_counted.h"],
@ -1215,6 +1230,7 @@ grpc_cc_library(
name = "dual_ref_counted",
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
public_hdrs = ["lib/gprpp/dual_ref_counted.h"],
@ -1410,6 +1426,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:flat_hash_set",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -1460,6 +1477,9 @@ grpc_cc_library(
hdrs = [
"lib/resource_quota/arena.h",
],
external_deps = [
"absl/log:log",
],
visibility = [
"@grpc:alt_grpc_base_legacy",
],
@ -1559,6 +1579,9 @@ grpc_cc_library(
hdrs = [
"lib/slice/slice_refcount.h",
],
external_deps = [
"absl/log:log",
],
public_hdrs = [
"//:include/grpc/slice.h",
],
@ -1626,6 +1649,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -1653,6 +1677,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:str_format",
],
visibility = ["@grpc:alt_grpc_base_legacy"],
@ -1674,6 +1699,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:str_format",
"absl/types:optional",
],
@ -1755,6 +1781,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"//:config_vars",
@ -1904,6 +1931,7 @@ grpc_cc_library(
"absl/container:flat_hash_set",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/time",
"absl/types:optional",
],
@ -1954,6 +1982,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/time",
"absl/types:optional",
],
@ -2111,6 +2140,7 @@ grpc_cc_library(
"absl/container:inlined_vector",
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2217,6 +2247,7 @@ grpc_cc_library(
],
external_deps = [
"absl/functional:any_invocable",
"absl/log:log",
"absl/status",
"absl/types:optional",
],
@ -2241,6 +2272,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2302,6 +2334,7 @@ grpc_cc_library(
external_deps = [
"absl/cleanup",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2334,6 +2367,7 @@ grpc_cc_library(
external_deps = [
"absl/cleanup",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2361,6 +2395,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2397,6 +2432,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2439,6 +2475,7 @@ grpc_cc_library(
hdrs = ["lib/event_engine/windows/windows_engine.h"],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2493,6 +2530,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -2522,6 +2560,7 @@ grpc_cc_library(
"absl/cleanup",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -2550,6 +2589,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings:str_format",
@ -2584,6 +2624,7 @@ grpc_cc_library(
external_deps = [
"absl/container:flat_hash_map",
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
],
@ -2618,6 +2659,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2644,6 +2686,9 @@ grpc_cc_library(
hdrs = [
"lib/event_engine/trace.h",
],
external_deps = [
"absl/log:log",
],
deps = [
"//:gpr",
"//:gpr_platform",
@ -2834,6 +2879,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2890,6 +2936,7 @@ grpc_cc_library(
hdrs = ["lib/transport/bdp_estimator.h"],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
deps = [
@ -3075,6 +3122,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/types:optional",
],
@ -3085,6 +3133,7 @@ grpc_cc_library(
"channel_fwd",
"channel_stack_trace",
"channel_stack_type",
"interception_chain",
"//:channel_stack_builder",
"//:debug_location",
"//:gpr",
@ -3102,6 +3151,7 @@ grpc_cc_library(
deps = [
"channel_args",
"//:channelz",
"//:event_engine_base_hdrs",
"//:gpr_platform",
],
)
@ -3151,7 +3201,10 @@ grpc_cc_library(
hdrs = [
"service_config/service_config_parser.h",
],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
deps = [
"channel_args",
@ -3180,6 +3233,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/strings",
"absl/strings:str_format",
@ -3355,6 +3409,7 @@ grpc_cc_library(
"client_channel/retry_service_config.h",
],
external_deps = [
"absl/log:log",
"absl/strings",
"absl/types:optional",
],
@ -3405,6 +3460,7 @@ grpc_cc_library(
"client_channel/backup_poller.h",
],
external_deps = [
"absl/log:log",
"absl/status",
],
language = "c++",
@ -3428,6 +3484,7 @@ grpc_cc_library(
"service_config/service_config_channel_arg_filter.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",
@ -3514,6 +3571,7 @@ grpc_cc_library(
hdrs = ["load_balancing/lb_policy_registry.h"],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3624,6 +3682,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3763,6 +3822,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
deps = [
@ -3810,6 +3870,7 @@ grpc_cc_library(
"lib/security/authorization/grpc_server_authz_filter.h",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3852,6 +3913,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/container:flat_hash_map",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3885,6 +3947,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3965,6 +4028,9 @@ grpc_cc_library(
hdrs = [
"tsi/local_transport_security.h",
],
external_deps = [
"absl/log:log",
],
language = "c++",
deps = [
"//:event_engine_base_hdrs",
@ -3986,6 +4052,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4033,6 +4100,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/strings:str_format",
@ -4078,6 +4146,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -4160,6 +4229,7 @@ grpc_cc_library(
"absl/container:inlined_vector",
"absl/functional:bind_front",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4246,6 +4316,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4308,6 +4379,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4354,6 +4426,7 @@ grpc_cc_library(
"lib/http/httpcli_ssl_credentials.h",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -4428,6 +4501,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4578,6 +4652,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -4659,6 +4734,7 @@ grpc_cc_library(
"ext/filters/message_size/message_size_filter.h",
],
external_deps = [
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/strings:str_format",
@ -4707,6 +4783,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -5099,6 +5176,7 @@ grpc_cc_library(
"absl/cleanup",
"absl/functional:bind_front",
"absl/log:check",
"absl/log:log",
"absl/memory",
"absl/random",
"absl/status",
@ -5283,6 +5361,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5361,6 +5440,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5421,6 +5501,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5471,6 +5552,7 @@ grpc_cc_library(
"load_balancing/xds/xds_cluster_manager.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5514,6 +5596,7 @@ grpc_cc_library(
"load_balancing/xds/xds_wrr_locality.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5583,6 +5666,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5630,6 +5714,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",
@ -5754,7 +5839,10 @@ grpc_cc_library(
hdrs = [
"lib/transport/connectivity_state.h",
],
external_deps = ["absl/status"],
external_deps = [
"absl/log:log",
"absl/status",
],
deps = [
"closure",
"error",
@ -5789,6 +5877,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5839,6 +5928,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -6013,6 +6103,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6061,6 +6152,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -6172,6 +6264,7 @@ grpc_cc_library(
],
external_deps = [
"absl/container:inlined_vector",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6216,6 +6309,7 @@ grpc_cc_library(
"ext/filters/backend_metrics/backend_metric_filter.h",
],
external_deps = [
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -6256,6 +6350,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6320,6 +6415,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/cleanup",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6361,7 +6457,10 @@ grpc_cc_library(
hdrs = [
"resolver/dns/dns_resolver_plugin.h",
],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
deps = [
"experiments",
@ -6385,6 +6484,7 @@ grpc_cc_library(
],
external_deps = [
"absl/functional:bind_front",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6418,6 +6518,7 @@ grpc_cc_library(
"resolver/sockaddr/sockaddr_resolver.cc",
],
external_deps = [
"absl/log:log",
"absl/status:statusor",
"absl/strings",
],
@ -6442,6 +6543,7 @@ grpc_cc_library(
"resolver/binder/binder_resolver.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6503,6 +6605,7 @@ grpc_cc_library(
"absl/container:flat_hash_map",
"absl/container:flat_hash_set",
"absl/log:check",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -6526,6 +6629,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -6587,6 +6691,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -6654,6 +6759,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/strings:str_format",
@ -6848,6 +6954,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings:str_format",
@ -6905,6 +7012,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6966,6 +7074,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6983,6 +7092,7 @@ grpc_cc_library(
"experiments",
"iomgr_fwd",
"metadata_batch",
"resource_quota",
"slice",
"slice_buffer",
"status_helper",
@ -7091,6 +7201,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -7144,6 +7255,7 @@ grpc_cc_library(
"ext/filters/logging/logging_filter.h",
],
external_deps = [
"absl/log:log",
"absl/numeric:int128",
"absl/random",
"absl/random:distributions",
@ -7222,7 +7334,10 @@ grpc_cc_library(
hdrs = [
"ext/transport/chaotic_good/chaotic_good_transport.h",
],
external_deps = ["absl/random"],
external_deps = [
"absl/log:log",
"absl/random",
],
language = "c++",
deps = [
"chaotic_good_frame",
@ -7251,6 +7366,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:flat_hash_map",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",
@ -7309,6 +7425,7 @@ grpc_cc_library(
"absl/container:flat_hash_map",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",
@ -7394,6 +7511,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"call_final_info",
@ -7504,6 +7622,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"1999",
@ -7641,6 +7760,7 @@ grpc_cc_library(
external_deps = [
"absl/container:flat_hash_map",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",
@ -7706,6 +7826,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",

@ -72,7 +72,7 @@ class ListenSocketNode;
namespace testing {
class CallCountingHelperPeer;
class ChannelNodePeer;
class SubchannelNodePeer;
} // namespace testing
// base class for all channelz entities
@ -228,9 +228,6 @@ class ChannelNode final : public BaseNode {
void RemoveChildSubchannel(intptr_t child_uuid);
private:
// Allows the channel trace test to access trace_.
friend class testing::ChannelNodePeer;
void PopulateChildRefs(Json::Object* json);
std::string target_;
@ -277,6 +274,9 @@ class SubchannelNode final : public BaseNode {
void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
private:
// Allows the channel trace test to access trace_.
friend class testing::SubchannelNodePeer;
std::atomic<grpc_connectivity_state> connectivity_state_{GRPC_CHANNEL_IDLE};
Mutex socket_mu_;
RefCountedPtr<SocketNode> child_socket_ ABSL_GUARDED_BY(socket_mu_);

@ -539,11 +539,11 @@ void RegisterLoggingFilter(LoggingSink* sink) {
g_logging_sink = sink;
CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) {
builder->channel_init()
->RegisterFilter<ServerLoggingFilter>(GRPC_SERVER_CHANNEL)
->RegisterV2Filter<ServerLoggingFilter>(GRPC_SERVER_CHANNEL)
// TODO(yashykt) : Figure out a good place to place this channel arg
.IfChannelArg("grpc.experimental.enable_observability", true);
builder->channel_init()
->RegisterFilter<ClientLoggingFilter>(GRPC_CLIENT_CHANNEL)
->RegisterV2Filter<ClientLoggingFilter>(GRPC_CLIENT_CHANNEL)
// TODO(yashykt) : Figure out a good place to place this channel arg
.IfChannelArg("grpc.experimental.enable_observability", true);
});

@ -235,37 +235,27 @@ auto ChaoticGoodServerTransport::DeserializeAndPushFragmentToNewCall(
FrameHeader frame_header, BufferPair buffers,
ChaoticGoodTransport& transport) {
ClientFragmentFrame fragment_frame;
ScopedArenaPtr arena(acceptor_->CreateArena());
ScopedArenaPtr arena(call_arena_allocator_->MakeArena());
absl::Status status = transport.DeserializeFrame(
frame_header, std::move(buffers), arena.get(), fragment_frame,
FrameLimits{1024 * 1024 * 1024, aligned_bytes_ - 1});
absl::optional<CallInitiator> call_initiator;
if (status.ok()) {
auto create_call_result = acceptor_->CreateCall(
std::move(fragment_frame.headers), arena.release());
if (grpc_chaotic_good_trace.enabled()) {
gpr_log(GPR_INFO,
"CHAOTIC_GOOD: DeserializeAndPushFragmentToNewCall: "
"create_call_result=%s",
create_call_result.ok()
? "ok"
: create_call_result.status().ToString().c_str());
}
if (create_call_result.ok()) {
call_initiator.emplace(std::move(*create_call_result));
auto add_result = NewStream(frame_header.stream_id, *call_initiator);
if (add_result.ok()) {
call_initiator->SpawnGuarded(
"server-write", [this, stream_id = frame_header.stream_id,
call_initiator = *call_initiator]() {
return CallOutboundLoop(stream_id, call_initiator);
});
} else {
call_initiator.reset();
status = add_result;
}
auto call =
MakeCallPair(std::move(fragment_frame.headers), event_engine_.get(),
arena.release(), call_arena_allocator_, nullptr);
call_initiator.emplace(std::move(call.initiator));
auto add_result = NewStream(frame_header.stream_id, *call_initiator);
if (add_result.ok()) {
call_destination_->StartCall(std::move(call.handler));
call_initiator->SpawnGuarded(
"server-write", [this, stream_id = frame_header.stream_id,
call_initiator = *call_initiator]() {
return CallOutboundLoop(stream_id, call_initiator);
});
} else {
status = create_call_result.status();
call_initiator.reset();
status = add_result;
}
}
return MaybePushFragmentIntoCall(std::move(call_initiator), std::move(status),
@ -366,10 +356,13 @@ ChaoticGoodServerTransport::ChaoticGoodServerTransport(
PromiseEndpoint data_endpoint,
std::shared_ptr<grpc_event_engine::experimental::EventEngine> event_engine,
HPackParser hpack_parser, HPackCompressor hpack_encoder)
: outgoing_frames_(4),
allocator_(args.GetObject<ResourceQuota>()
->memory_quota()
->CreateMemoryAllocator("chaotic-good")) {
: call_arena_allocator_(MakeRefCounted<CallArenaAllocator>(
args.GetObject<ResourceQuota>()
->memory_quota()
->CreateMemoryAllocator("chaotic-good"),
1024)),
event_engine_(event_engine),
outgoing_frames_(4) {
auto transport = MakeRefCounted<ChaoticGoodTransport>(
std::move(control_endpoint), std::move(data_endpoint),
std::move(hpack_parser), std::move(hpack_encoder));
@ -381,20 +374,25 @@ ChaoticGoodServerTransport::ChaoticGoodServerTransport(
OnTransportActivityDone("reader"));
}
void ChaoticGoodServerTransport::SetAcceptor(Acceptor* acceptor) {
CHECK_EQ(acceptor_, nullptr);
CHECK_NE(acceptor, nullptr);
acceptor_ = acceptor;
void ChaoticGoodServerTransport::SetCallDestination(
RefCountedPtr<UnstartedCallDestination> call_destination) {
CHECK(call_destination_ == nullptr);
CHECK(call_destination != nullptr);
call_destination_ = call_destination;
got_acceptor_.Set();
}
ChaoticGoodServerTransport::~ChaoticGoodServerTransport() {
if (writer_ != nullptr) {
writer_.reset();
}
if (reader_ != nullptr) {
reader_.reset();
void ChaoticGoodServerTransport::Orphan() {
ActivityPtr writer;
ActivityPtr reader;
{
MutexLock lock(&mu_);
writer = std::move(writer_);
reader = std::move(reader_);
}
writer.reset();
reader.reset();
Unref();
}
void ChaoticGoodServerTransport::AbortWithError() {

@ -86,7 +86,6 @@ class ChaoticGoodServerTransport final : public ServerTransport {
std::shared_ptr<grpc_event_engine::experimental::EventEngine>
event_engine,
HPackParser hpack_parser, HPackCompressor hpack_encoder);
~ChaoticGoodServerTransport() override;
FilterStackTransport* filter_stack_transport() override { return nullptr; }
ClientTransport* client_transport() override { return nullptr; }
@ -96,9 +95,10 @@ class ChaoticGoodServerTransport final : public ServerTransport {
void SetPollsetSet(grpc_stream*, grpc_pollset_set*) override {}
void PerformOp(grpc_transport_op*) override;
grpc_endpoint* GetEndpoint() override { return nullptr; }
void Orphan() override { Unref(); }
void Orphan() override;
void SetAcceptor(Acceptor* acceptor) override;
void SetCallDestination(
RefCountedPtr<UnstartedCallDestination> call_destination) override;
void AbortWithError();
private:
@ -137,7 +137,10 @@ class ChaoticGoodServerTransport final : public ServerTransport {
auto PushFragmentIntoCall(CallInitiator call_initiator,
ClientFragmentFrame frame, uint32_t stream_id);
Acceptor* acceptor_ = nullptr;
RefCountedPtr<UnstartedCallDestination> call_destination_;
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
const std::shared_ptr<grpc_event_engine::experimental::EventEngine>
event_engine_;
InterActivityLatch<void> got_acceptor_;
MpscReceiver<ServerFrame> outgoing_frames_;
// Assigned aligned bytes from setting frame.
@ -146,7 +149,6 @@ class ChaoticGoodServerTransport final : public ServerTransport {
// Map of stream incoming server frames, key is stream_id.
StreamMap stream_map_ ABSL_GUARDED_BY(mu_);
uint32_t last_seen_new_stream_id_ = 0;
grpc_event_engine::experimental::MemoryAllocator allocator_;
ActivityPtr writer_ ABSL_GUARDED_BY(mu_);
ActivityPtr reader_ ABSL_GUARDED_BY(mu_);
ConnectivityStateTracker state_tracker_ ABSL_GUARDED_BY(mu_){

@ -41,6 +41,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"cronet_c_for_grpc",
],
language = "c++",

@ -28,6 +28,7 @@
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/surface/channel_create.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/server/server.h"
@ -39,8 +40,18 @@ class InprocClientTransport;
class InprocServerTransport final : public ServerTransport {
public:
void SetAcceptor(Acceptor* acceptor) override {
acceptor_ = acceptor;
explicit InprocServerTransport(const ChannelArgs& args)
: event_engine_(
args.GetObjectRef<grpc_event_engine::experimental::EventEngine>()),
call_arena_allocator_(MakeRefCounted<CallArenaAllocator>(
args.GetObject<ResourceQuota>()
->memory_quota()
->CreateMemoryAllocator("inproc_server"),
1024)) {}
void SetCallDestination(
RefCountedPtr<UnstartedCallDestination> unstarted_call_handler) override {
unstarted_call_handler_ = unstarted_call_handler;
ConnectionState expect = ConnectionState::kInitial;
state_.compare_exchange_strong(expect, ConnectionState::kReady,
std::memory_order_acq_rel,
@ -95,7 +106,11 @@ class InprocServerTransport final : public ServerTransport {
case ConnectionState::kReady:
break;
}
return acceptor_->CreateCall(std::move(md), acceptor_->CreateArena());
auto* arena = call_arena_allocator_->MakeArena();
auto server_call = MakeCallPair(std::move(md), event_engine_.get(), arena,
call_arena_allocator_, nullptr);
unstarted_call_handler_->StartCall(std::move(server_call.handler));
return std::move(server_call.initiator);
}
OrphanablePtr<InprocClientTransport> MakeClientTransport();
@ -105,11 +120,14 @@ class InprocServerTransport final : public ServerTransport {
std::atomic<ConnectionState> state_{ConnectionState::kInitial};
std::atomic<bool> disconnecting_{false};
Acceptor* acceptor_;
RefCountedPtr<UnstartedCallDestination> unstarted_call_handler_;
absl::Status disconnect_error_;
Mutex state_tracker_mu_;
ConnectivityStateTracker state_tracker_ ABSL_GUARDED_BY(state_tracker_mu_){
"inproc_server_transport", GRPC_CHANNEL_CONNECTING};
const std::shared_ptr<grpc_event_engine::experimental::EventEngine>
event_engine_;
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
};
class InprocClientTransport final : public ClientTransport {
@ -118,16 +136,19 @@ class InprocClientTransport final : public ClientTransport {
RefCountedPtr<InprocServerTransport> server_transport)
: server_transport_(std::move(server_transport)) {}
void StartCall(CallHandler call_handler) override {
call_handler.SpawnGuarded(
void StartCall(CallHandler child_call_handler) override {
child_call_handler.SpawnGuarded(
"pull_initial_metadata",
TrySeq(call_handler.PullClientInitialMetadata(),
TrySeq(child_call_handler.PullClientInitialMetadata(),
[server_transport = server_transport_,
call_handler](ClientMetadataHandle md) {
auto call_initiator =
child_call_handler](ClientMetadataHandle md) {
auto server_call_initiator =
server_transport->AcceptCall(std::move(md));
if (!call_initiator.ok()) return call_initiator.status();
ForwardCall(call_handler, std::move(*call_initiator));
if (!server_call_initiator.ok()) {
return server_call_initiator.status();
}
ForwardCall(child_call_handler,
std::move(*server_call_initiator));
return absl::OkStatus();
}));
}
@ -155,7 +176,6 @@ class InprocClientTransport final : public ClientTransport {
bool UsePromiseBasedTransport() {
if (!IsPromiseBasedInprocTransportEnabled()) return false;
CHECK(IsPromiseBasedClientCallEnabled());
CHECK(IsPromiseBasedServerCallEnabled());
return true;
}
@ -180,7 +200,7 @@ OrphanablePtr<Channel> MakeLameChannel(absl::string_view why,
OrphanablePtr<Channel> MakeInprocChannel(Server* server,
ChannelArgs client_channel_args) {
auto transports = MakeInProcessTransportPair();
auto transports = MakeInProcessTransportPair(server->channel_args());
auto client_transport = std::move(transports.first);
auto server_transport = std::move(transports.second);
auto error =
@ -205,8 +225,9 @@ OrphanablePtr<Channel> MakeInprocChannel(Server* server,
} // namespace
std::pair<OrphanablePtr<Transport>, OrphanablePtr<Transport>>
MakeInProcessTransportPair() {
auto server_transport = MakeOrphanable<InprocServerTransport>();
MakeInProcessTransportPair(const ChannelArgs& server_channel_args) {
auto server_transport =
MakeOrphanable<InprocServerTransport>(server_channel_args);
auto client_transport = server_transport->MakeClientTransport();
return std::make_pair(std::move(client_transport),
std::move(server_transport));

@ -30,7 +30,7 @@ extern grpc_core::TraceFlag grpc_inproc_trace;
namespace grpc_core {
std::pair<OrphanablePtr<Transport>, OrphanablePtr<Transport>>
MakeInProcessTransportPair();
MakeInProcessTransportPair(const ChannelArgs& server_channel_args);
}

@ -305,13 +305,6 @@ grpc_core::NextPromiseFactory ClientNext(grpc_channel_element* elem) {
};
}
grpc_core::NextPromiseFactory ServerNext(grpc_channel_element* elem) {
return [elem](grpc_core::CallArgs args) {
return elem->filter->make_call_promise(elem, std::move(args),
ServerNext(elem - 1));
};
}
} // namespace
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
@ -319,12 +312,6 @@ grpc_channel_stack::MakeClientCallPromise(grpc_core::CallArgs call_args) {
return ClientNext(grpc_channel_stack_element(this, 0))(std::move(call_args));
}
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
grpc_channel_stack::MakeServerCallPromise(grpc_core::CallArgs call_args) {
return ServerNext(grpc_channel_stack_element(this, this->count - 1))(
std::move(call_args));
}
void grpc_channel_stack::InitClientCallSpine(
grpc_core::CallSpineInterface* call) {
for (size_t i = 0; i < count; i++) {
@ -338,19 +325,6 @@ void grpc_channel_stack::InitClientCallSpine(
}
}
void grpc_channel_stack::InitServerCallSpine(
grpc_core::CallSpineInterface* call) {
for (size_t i = 0; i < count; i++) {
auto* elem = grpc_channel_stack_element(this, count - 1 - i);
if (elem->filter->init_call == nullptr) {
grpc_core::Crash(
absl::StrCat("Filter '", elem->filter->name,
"' does not support the call-v3 interface"));
}
elem->filter->init_call(elem, call);
}
}
void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
grpc_call_element* elem,
grpc_transport_stream_op_batch* op) {

@ -241,7 +241,6 @@ struct grpc_channel_stack {
MakeServerCallPromise(grpc_core::CallArgs call_args);
void InitClientCallSpine(grpc_core::CallSpineInterface* call);
void InitServerCallSpine(grpc_core::CallSpineInterface* call);
};
// A call stack tracks a set of related filters for one call, and guarantees

@ -88,23 +88,17 @@ const char* const additional_constraints_promise_based_client_call = "{}";
const uint8_t required_experiments_promise_based_client_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener)};
const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const char* const description_chaotic_good =
"If set, enable the chaotic good load transport (this is mostly here for "
"testing)";
const char* const additional_constraints_chaotic_good = "{}";
const uint8_t required_experiments_chaotic_good[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const uint8_t required_experiments_promise_based_inproc_transport[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -184,15 +178,13 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call,
required_experiments_promise_based_client_call, 2, false, true},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, nullptr, 0, false, true},
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 1,
false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 2, false, false},
required_experiments_promise_based_inproc_transport, 1, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
@ -288,23 +280,17 @@ const char* const additional_constraints_promise_based_client_call = "{}";
const uint8_t required_experiments_promise_based_client_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener)};
const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const char* const description_chaotic_good =
"If set, enable the chaotic good load transport (this is mostly here for "
"testing)";
const char* const additional_constraints_chaotic_good = "{}";
const uint8_t required_experiments_chaotic_good[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const uint8_t required_experiments_promise_based_inproc_transport[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -384,15 +370,13 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call,
required_experiments_promise_based_client_call, 2, false, true},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, nullptr, 0, false, true},
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 1,
false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 2, false, false},
required_experiments_promise_based_inproc_transport, 1, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
@ -488,23 +472,17 @@ const char* const additional_constraints_promise_based_client_call = "{}";
const uint8_t required_experiments_promise_based_client_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener)};
const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const char* const description_chaotic_good =
"If set, enable the chaotic good load transport (this is mostly here for "
"testing)";
const char* const additional_constraints_chaotic_good = "{}";
const uint8_t required_experiments_chaotic_good[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const uint8_t required_experiments_promise_based_inproc_transport[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -584,15 +562,13 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call,
required_experiments_promise_based_client_call, 2, false, true},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, nullptr, 0, false, true},
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 1,
false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 2, false, false},
required_experiments_promise_based_inproc_transport, 1, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",

@ -79,7 +79,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
@ -119,7 +118,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
@ -159,7 +157,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
@ -195,7 +192,6 @@ enum ExperimentIds {
kExperimentIdPendingQueueCap,
kExperimentIdPickFirstNew,
kExperimentIdPromiseBasedClientCall,
kExperimentIdPromiseBasedServerCall,
kExperimentIdChaoticGood,
kExperimentIdPromiseBasedInprocTransport,
kExperimentIdRstpit,
@ -277,10 +273,6 @@ inline bool IsPickFirstNewEnabled() {
inline bool IsPromiseBasedClientCallEnabled() {
return IsExperimentEnabled(kExperimentIdPromiseBasedClientCall);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_SERVER_CALL
inline bool IsPromiseBasedServerCallEnabled() {
return IsExperimentEnabled(kExperimentIdPromiseBasedServerCall);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CHAOTIC_GOOD
inline bool IsChaoticGoodEnabled() {
return IsExperimentEnabled(kExperimentIdChaoticGood);

@ -64,7 +64,7 @@
If set, enable the chaotic good load transport (this is mostly here for testing)
expiry: 2024/09/09
owner: ctiller@google.com
requires: [promise_based_client_call, promise_based_server_call]
requires: [promise_based_client_call]
test_tags: [core_end2end_test]
- name: client_privacy
description:
@ -170,14 +170,7 @@
owner: ctiller@google.com
test_tags: []
allow_in_fuzzing_config: false # experiment currently crashes if enabled
requires: [promise_based_client_call, promise_based_server_call]
- name: promise_based_server_call
description:
If set, use the new gRPC promise based call code when it's appropriate
(ie when all filters in a stack are promise based)
expiry: 2024/06/14
owner: ctiller@google.com
test_tags: ["core_end2end_test", "logging_test"]
requires: [promise_based_client_call]
- name: rstpit
description:
On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short duration

@ -94,8 +94,6 @@
ios: broken
windows: broken
posix: false
- name: promise_based_server_call
default: false
- name: rstpit
default: false
- name: schedule_cancellation_over_write

@ -17,6 +17,7 @@
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/meta/type_traits.h"
#include <grpc/support/port_platform.h>
@ -63,6 +64,10 @@ auto WrapInPoll(T&& x) -> decltype(PollWrapper<T>::Wrap(std::forward<T>(x))) {
return PollWrapper<T>::Wrap(std::forward<T>(x));
}
// T -> T, const T& -> T
template <typename T>
using RemoveCVRef = absl::remove_cv_t<absl::remove_reference_t<T>>;
template <typename F, typename SfinaeVoid = void>
class PromiseLike;
@ -73,7 +78,7 @@ template <typename F>
class PromiseLike<F, absl::enable_if_t<!std::is_void<
typename std::result_of<F()>::type>::value>> {
private:
GPR_NO_UNIQUE_ADDRESS F f_;
GPR_NO_UNIQUE_ADDRESS RemoveCVRef<F> f_;
public:
// NOLINTNEXTLINE - internal detail that drastically simplifies calling code.
@ -82,10 +87,6 @@ class PromiseLike<F, absl::enable_if_t<!std::is_void<
using Result = typename PollTraits<decltype(WrapInPoll(f_()))>::Type;
};
// T -> T, const T& -> T
template <typename T>
using RemoveCVRef = absl::remove_cv_t<absl::remove_reference_t<T>>;
} // namespace promise_detail
} // namespace grpc_core

@ -171,6 +171,8 @@ class ValueOrFailure {
T& value() { return value_.value(); }
const T& operator*() const { return *value_; }
T& operator*() { return *value_; }
const T* operator->() const { return &*value_; }
T* operator->() { return &*value_; }
bool operator==(const ValueOrFailure& other) const {
return value_ == other.value_;

File diff suppressed because it is too large Load Diff

@ -82,7 +82,7 @@ class Call : public CppImplOf<Call, grpc_call>,
public grpc_event_engine::experimental::EventEngine::
Closure /* for deadlines */ {
public:
Arena* arena() { return arena_; }
virtual Arena* arena() = 0;
bool is_client() const { return is_client_; }
virtual void ContextSet(grpc_context_index elem, void* value,
@ -92,7 +92,7 @@ class Call : public CppImplOf<Call, grpc_call>,
void CancelWithStatus(grpc_status_code status, const char* description);
virtual void CancelWithError(grpc_error_handle error) = 0;
virtual void SetCompletionQueue(grpc_completion_queue* cq) = 0;
char* GetPeer();
virtual char* GetPeer() = 0;
virtual grpc_call_error StartBatch(const grpc_op* ops, size_t nops,
void* notify_tag,
bool is_notify_tag_closure) = 0;
@ -157,25 +157,15 @@ class Call : public CppImplOf<Call, grpc_call>,
Call* sibling_prev = nullptr;
};
Call(Arena* arena, bool is_client, Timestamp send_deadline,
RefCountedPtr<Channel> channel)
: channel_(std::move(channel)),
arena_(arena),
send_deadline_(send_deadline),
is_client_(is_client) {
DCHECK_NE(arena_, nullptr);
DCHECK(channel_ != nullptr);
}
Call(bool is_client, Timestamp send_deadline,
grpc_event_engine::experimental::EventEngine* event_engine)
: send_deadline_(send_deadline),
is_client_(is_client),
event_engine_(event_engine) {}
~Call() override = default;
void DeleteThis();
ParentCall* GetOrCreateParentCall();
ParentCall* parent_call();
Channel* channel() const {
DCHECK(channel_ != nullptr);
return channel_.get();
}
absl::Status InitParent(Call* parent, uint32_t propagation_mask);
void PublishToParent(Call* parent);
@ -221,9 +211,9 @@ class Call : public CppImplOf<Call, grpc_call>,
gpr_cycle_counter start_time() const { return start_time_; }
virtual grpc_compression_options compression_options() = 0;
private:
RefCountedPtr<Channel> channel_;
Arena* const arena_;
std::atomic<ParentCall*> parent_call_{nullptr};
ChildCall* child_ = nullptr;
Timestamp send_deadline_;
@ -247,34 +237,13 @@ class Call : public CppImplOf<Call, grpc_call>,
Timestamp deadline_ ABSL_GUARDED_BY(deadline_mu_) = Timestamp::InfFuture();
grpc_event_engine::experimental::EventEngine::TaskHandle ABSL_GUARDED_BY(
deadline_mu_) deadline_task_;
grpc_event_engine::experimental::EventEngine* const event_engine_;
gpr_cycle_counter start_time_ = gpr_get_cycle_counter();
};
class BasicPromiseBasedCall;
class ServerPromiseBasedCall;
class ServerCallContext {
public:
virtual void PublishInitialMetadata(
ClientMetadataHandle metadata,
grpc_metadata_array* publish_initial_metadata) = 0;
// Construct the top of the server call promise for the v2 filter stack.
// TODO(ctiller): delete when v3 is available.
virtual ArenaPromise<ServerMetadataHandle> MakeTopOfServerCallPromise(
CallArgs call_args, grpc_completion_queue* cq,
absl::FunctionRef<void(grpc_call* call)> publish) = 0;
// Server stream data as supplied by the transport (so we can link the
// transport stream up with the call again).
// TODO(ctiller): legacy API - once we move transports to promises we'll
// create the promise directly and not need to pass around this token.
virtual const void* server_stream_data() = 0;
protected:
~ServerCallContext() = default;
};
// TODO(ctiller): move more call things into this type
class CallContext {
public:
@ -300,8 +269,6 @@ class CallContext {
gpr_atm* peer_string_atm_ptr();
gpr_cycle_counter call_start_time() { return start_time_; }
ServerCallContext* server_call_context();
void set_traced(bool traced) { traced_ = traced; }
bool traced() const { return traced_; }
@ -329,9 +296,10 @@ template <>
struct ContextType<CallContext> {};
// TODO(ctiller): remove once call-v3 finalized
RefCountedPtr<CallSpineInterface> MakeServerCall(
ClientMetadataHandle client_initial_metadata, ServerInterface* server,
Channel* channel, Arena* arena);
grpc_call* MakeServerCall(CallHandler call_handler,
ClientMetadataHandle client_initial_metadata,
ServerInterface* server, grpc_completion_queue* cq,
grpc_metadata_array* publish_initial_metadata);
} // namespace grpc_core

@ -104,9 +104,9 @@ ChannelInit::FilterRegistration::ExcludeFromMinimalStack() {
ChannelInit::FilterRegistration& ChannelInit::Builder::RegisterFilter(
grpc_channel_stack_type type, const grpc_channel_filter* filter,
const ChannelFilterVtable* vtable, SourceLocation registration_source) {
FilterAdder filter_adder, SourceLocation registration_source) {
filters_[type].emplace_back(std::make_unique<FilterRegistration>(
filter, vtable, registration_source));
filter, filter_adder, registration_source));
return *filters_[type].back();
}
@ -223,9 +223,10 @@ ChannelInit::StackConfig ChannelInit::BuildStackConfig(
while (!dependencies.empty()) {
auto filter = take_ready_dependency();
auto* registration = filter_to_registration[filter];
filters.emplace_back(
filter, registration->vtable_, std::move(registration->predicates_),
registration->skip_v3_, registration->registration_source_);
filters.emplace_back(filter, registration->filter_adder_,
std::move(registration->predicates_),
registration->skip_v3_,
registration->registration_source_);
for (auto& p : dependencies) {
p.second.erase(filter);
}
@ -406,78 +407,21 @@ bool ChannelInit::CreateStack(ChannelStackBuilder* builder) const {
return true;
}
absl::StatusOr<ChannelInit::StackSegment> ChannelInit::CreateStackSegment(
grpc_channel_stack_type type, const ChannelArgs& args) const {
void ChannelInit::AddToInterceptionChainBuilder(
grpc_channel_stack_type type, InterceptionChainBuilder& builder) const {
const auto& stack_config = stack_configs_[type];
std::vector<StackSegment::ChannelFilter> filters;
size_t channel_data_size = 0;
size_t channel_data_alignment = 0;
// Based on predicates build a list of filters to include in this segment.
for (const auto& filter : stack_config.filters) {
if (filter.skip_v3) continue;
if (!filter.CheckPredicates(args)) continue;
if (filter.vtable == nullptr) {
return absl::InvalidArgumentError(
if (!filter.CheckPredicates(builder.channel_args())) continue;
if (filter.filter_adder == nullptr) {
builder.Fail(absl::InvalidArgumentError(
absl::StrCat("Filter ", NameFromChannelFilter(filter.filter),
" has no v3-callstack vtable"));
" has no v3-callstack vtable")));
return;
}
channel_data_alignment =
std::max(channel_data_alignment, filter.vtable->alignment);
if (channel_data_size % filter.vtable->alignment != 0) {
channel_data_size += filter.vtable->alignment -
(channel_data_size % filter.vtable->alignment);
}
filters.push_back({channel_data_size, filter.vtable});
channel_data_size += filter.vtable->size;
}
// Shortcut for empty segments.
if (filters.empty()) return StackSegment();
// Allocate memory for the channel data, initialize channel filters into it.
uint8_t* p = static_cast<uint8_t*>(
gpr_malloc_aligned(channel_data_size, channel_data_alignment));
for (size_t i = 0; i < filters.size(); i++) {
auto r = filters[i].vtable->init(p + filters[i].offset, args);
if (!r.ok()) {
for (size_t j = 0; j < i; j++) {
filters[j].vtable->destroy(p + filters[j].offset);
}
gpr_free_aligned(p);
return r;
}
}
return StackSegment(std::move(filters), p);
}
///////////////////////////////////////////////////////////////////////////////
// ChannelInit::StackSegment
ChannelInit::StackSegment::StackSegment(std::vector<ChannelFilter> filters,
uint8_t* channel_data)
: data_(MakeRefCounted<ChannelData>(std::move(filters), channel_data)) {}
void ChannelInit::StackSegment::AddToCallFilterStack(
CallFilters::StackBuilder& builder) {
if (data_ == nullptr) return;
data_->AddToCallFilterStack(builder);
builder.AddOwnedObject(data_);
};
ChannelInit::StackSegment::ChannelData::ChannelData(
std::vector<ChannelFilter> filters, uint8_t* channel_data)
: filters_(std::move(filters)), channel_data_(channel_data) {}
void ChannelInit::StackSegment::ChannelData::AddToCallFilterStack(
CallFilters::StackBuilder& builder) {
for (const auto& filter : filters_) {
filter.vtable->add_to_stack_builder(channel_data_ + filter.offset, builder);
}
}
ChannelInit::StackSegment::ChannelData::~ChannelData() {
for (const auto& filter : filters_) {
filter.vtable->destroy(channel_data_ + filter.offset);
filter.filter_adder(builder);
}
gpr_free_aligned(channel_data_);
}
} // namespace grpc_core

@ -38,6 +38,7 @@
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_filters.h"
#include "src/core/lib/transport/interception_chain.h"
/// This module provides a way for plugins (and the grpc core library itself)
/// to register mutators for channel stacks.
@ -68,6 +69,8 @@ class ChannelInit {
using InclusionPredicate = absl::AnyInvocable<bool(const ChannelArgs&) const>;
// Post processor for the channel stack - applied in PostProcessorSlot order
using PostProcessor = absl::AnyInvocable<void(ChannelStackBuilder&) const>;
// Function that can be called to add a filter to a stack builder
using FilterAdder = void (*)(InterceptionChainBuilder&);
// Post processing slots - up to one PostProcessor per slot can be registered
// They run after filters registered are added to the channel stack builder,
// but before Build is called - allowing ad-hoc mutation to the channel stack.
@ -77,25 +80,15 @@ class ChannelInit {
kCount
};
// Vtable-like data structure for channel data initialization
struct ChannelFilterVtable {
size_t size;
size_t alignment;
absl::Status (*init)(void* data, const ChannelArgs& args);
void (*destroy)(void* data);
void (*add_to_stack_builder)(void* data,
CallFilters::StackBuilder& builder);
};
class FilterRegistration {
public:
// TODO(ctiller): Remove grpc_channel_filter* arg when that can be
// deprecated (once filter stack is removed).
explicit FilterRegistration(const grpc_channel_filter* filter,
const ChannelFilterVtable* vtable,
FilterAdder filter_adder,
SourceLocation registration_source)
: filter_(filter),
vtable_(vtable),
filter_adder_(filter_adder),
registration_source_(registration_source) {}
FilterRegistration(const FilterRegistration&) = delete;
FilterRegistration& operator=(const FilterRegistration&) = delete;
@ -170,7 +163,7 @@ class ChannelInit {
private:
friend class ChannelInit;
const grpc_channel_filter* const filter_;
const ChannelFilterVtable* const vtable_;
const FilterAdder filter_adder_;
std::vector<const grpc_channel_filter*> after_;
std::vector<const grpc_channel_filter*> before_;
std::vector<InclusionPredicate> predicates_;
@ -188,16 +181,17 @@ class ChannelInit {
// properties of the filter being registered.
// TODO(ctiller): remove in favor of the version that does not mention
// grpc_channel_filter
FilterRegistration& RegisterFilter(
grpc_channel_stack_type type, const grpc_channel_filter* filter,
const ChannelFilterVtable* vtable = nullptr,
SourceLocation registration_source = {});
FilterRegistration& RegisterFilter(grpc_channel_stack_type type,
const grpc_channel_filter* filter,
FilterAdder filter_adder = nullptr,
SourceLocation registration_source = {});
template <typename Filter>
FilterRegistration& RegisterFilter(
grpc_channel_stack_type type, SourceLocation registration_source = {}) {
return RegisterFilter(type, &Filter::kFilter,
VtableForType<Filter>::vtable(),
registration_source);
return RegisterFilter(
type, &Filter::kFilter,
[](InterceptionChainBuilder& builder) { builder.Add<Filter>(); },
registration_source);
}
// Filter does not participate in v3
@ -232,58 +226,13 @@ class ChannelInit {
[static_cast<int>(PostProcessorSlot::kCount)];
};
// A set of channel filters that can be added to a call stack.
// TODO(ctiller): move this out so it can be used independently of
// the global registration mechanisms.
class StackSegment final {
public:
// Registration of one channel filter in the stack.
struct ChannelFilter {
size_t offset;
const ChannelFilterVtable* vtable;
};
StackSegment() = default;
explicit StackSegment(std::vector<ChannelFilter> filters,
uint8_t* channel_data);
StackSegment(const StackSegment& other) = delete;
StackSegment& operator=(const StackSegment& other) = delete;
StackSegment(StackSegment&& other) noexcept = default;
StackSegment& operator=(StackSegment&& other) = default;
// Add this segment to a call filter stack builder
void AddToCallFilterStack(CallFilters::StackBuilder& builder);
private:
// Combined channel data for the stack
class ChannelData : public RefCounted<ChannelData> {
public:
explicit ChannelData(std::vector<ChannelFilter> filters,
uint8_t* channel_data);
~ChannelData() override;
void AddToCallFilterStack(CallFilters::StackBuilder& builder);
private:
std::vector<ChannelFilter> filters_;
uint8_t* channel_data_;
};
RefCountedPtr<ChannelData> data_;
};
/// Construct a channel stack of some sort: see channel_stack.h for details
/// \a builder is the channel stack builder to build into.
GRPC_MUST_USE_RESULT
bool CreateStack(ChannelStackBuilder* builder) const;
// Create a segment of a channel stack.
// Terminators and post processors are not included in this construction:
// terminators are a legacy filter-stack concept, and post processors
// need to migrate to other mechanisms.
// TODO(ctiller): figure out other mechanisms.
absl::StatusOr<StackSegment> CreateStackSegment(
grpc_channel_stack_type type, const ChannelArgs& args) const;
void AddToInterceptionChainBuilder(grpc_channel_stack_type type,
InterceptionChainBuilder& builder) const;
private:
// The type of object returned by a filter's Create method.
@ -292,16 +241,16 @@ class ChannelInit {
typename decltype(T::Create(ChannelArgs(), {}))::value_type;
struct Filter {
Filter(const grpc_channel_filter* filter, const ChannelFilterVtable* vtable,
Filter(const grpc_channel_filter* filter, FilterAdder filter_adder,
std::vector<InclusionPredicate> predicates, bool skip_v3,
SourceLocation registration_source)
: filter(filter),
vtable(vtable),
filter_adder(filter_adder),
predicates(std::move(predicates)),
registration_source(registration_source),
skip_v3(skip_v3) {}
const grpc_channel_filter* filter;
const ChannelFilterVtable* vtable;
const FilterAdder filter_adder;
std::vector<InclusionPredicate> predicates;
SourceLocation registration_source;
bool skip_v3 = false;
@ -313,17 +262,6 @@ class ChannelInit {
std::vector<PostProcessor> post_processors;
};
template <typename T, typename = void>
struct VtableForType {
static const ChannelFilterVtable* vtable() { return nullptr; }
};
template <typename T>
struct VtableForType<T, absl::void_t<typename T::Call>> {
static const ChannelFilterVtable kVtable;
static const ChannelFilterVtable* vtable() { return &kVtable; }
};
StackConfig stack_configs_[GRPC_NUM_CHANNEL_STACK_TYPES];
static StackConfig BuildStackConfig(
@ -331,22 +269,6 @@ class ChannelInit {
PostProcessor* post_processors, grpc_channel_stack_type type);
};
template <typename T>
const ChannelInit::ChannelFilterVtable
ChannelInit::VtableForType<T, absl::void_t<typename T::Call>>::kVtable = {
sizeof(CreatedType<T>), alignof(CreatedType<T>),
[](void* data, const ChannelArgs& args) -> absl::Status {
// TODO(ctiller): fill in ChannelFilter::Args (2nd arg)
absl::StatusOr<CreatedType<T>> r = T::Create(args, {});
if (!r.ok()) return r.status();
new (data) CreatedType<T>(std::move(*r));
return absl::OkStatus();
},
[](void* data) { Destruct(static_cast<CreatedType<T>*>(data)); },
[](void* data, CallFilters::StackBuilder& builder) {
builder.Add(static_cast<CreatedType<T>*>(data)->get());
}};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_SURFACE_CHANNEL_INIT_H

@ -66,10 +66,10 @@ static bool g_shutting_down ABSL_GUARDED_BY(g_init_mu) = false;
namespace grpc_core {
void RegisterSecurityFilters(CoreConfiguration::Builder* builder) {
builder->channel_init()
->RegisterFilter<ClientAuthFilter>(GRPC_CLIENT_SUBCHANNEL)
->RegisterV2Filter<ClientAuthFilter>(GRPC_CLIENT_SUBCHANNEL)
.IfHasChannelArg(GRPC_ARG_SECURITY_CONNECTOR);
builder->channel_init()
->RegisterFilter<ClientAuthFilter>(GRPC_CLIENT_DIRECT_CHANNEL)
->RegisterV2Filter<ClientAuthFilter>(GRPC_CLIENT_DIRECT_CHANNEL)
.IfHasChannelArg(GRPC_ARG_SECURITY_CONNECTOR);
builder->channel_init()
->RegisterFilter<ServerAuthFilter>(GRPC_SERVER_CHANNEL)

@ -51,6 +51,24 @@ class CallDestination : public DualRefCounted<CallDestination> {
virtual void HandleCall(CallHandler unstarted_call_handler) = 0;
};
template <typename HC>
auto MakeCallDestinationFromHandlerFunction(HC handle_call) {
class Impl : public CallDestination {
public:
explicit Impl(HC handle_call) : handle_call_(std::move(handle_call)) {}
void Orphaned() override {}
void HandleCall(CallHandler call_handler) override {
handle_call_(std::move(call_handler));
}
private:
HC handle_call_;
};
return MakeRefCounted<Impl>(std::move(handle_call));
}
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_TRANSPORT_CALL_DESTINATION_H

@ -1245,6 +1245,42 @@ const NoInterceptor
template <typename Fn>
const NoInterceptor ServerTrailingMetadataInterceptor<Fn>::Call::OnFinalize;
template <typename Fn>
class ClientInitialMetadataInterceptor {
public:
class Call {
public:
auto OnClientInitialMetadata(ClientMetadata& md,
ClientInitialMetadataInterceptor* filter) {
return filter->fn_(md);
}
static const NoInterceptor OnServerInitialMetadata;
static const NoInterceptor OnClientToServerMessage;
static const NoInterceptor OnServerToClientMessage;
static const NoInterceptor OnServerTrailingMetadata;
static const NoInterceptor OnFinalize;
};
explicit ClientInitialMetadataInterceptor(Fn fn) : fn_(std::move(fn)) {}
private:
GPR_NO_UNIQUE_ADDRESS Fn fn_;
};
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnServerInitialMetadata;
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnClientToServerMessage;
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnServerToClientMessage;
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnServerTrailingMetadata;
template <typename Fn>
const NoInterceptor ClientInitialMetadataInterceptor<Fn>::Call::OnFinalize;
} // namespace filters_detail
// Execution environment for a stack of filters.
@ -1302,6 +1338,14 @@ class CallFilters {
AddOwnedObject([](void* p) { delete static_cast<T*>(p); }, p.release());
}
template <typename Fn>
void AddOnClientInitialMetadata(Fn fn) {
auto filter = std::make_unique<
filters_detail::ClientInitialMetadataInterceptor<Fn>>(std::move(fn));
Add(filter.get());
AddOwnedObject(std::move(filter));
}
template <typename Fn>
void AddOnServerTrailingMetadata(Fn fn) {
auto filter = std::make_unique<

@ -518,6 +518,8 @@ class CallHandler {
auto PullMessage() { return spine_->PullClientToServerMessage(); }
auto WasCancelled() { return spine_->WasCancelled(); }
template <typename PromiseFactory>
void SpawnGuarded(absl::string_view name, PromiseFactory promise_factory,
DebugLocation whence = {}) {
@ -536,11 +538,15 @@ class CallHandler {
Arena* arena() { return spine_->arena(); }
grpc_event_engine::experimental::EventEngine* event_engine() {
grpc_event_engine::experimental::EventEngine* event_engine() const {
return DownCast<CallSpine*>(spine_.get())->event_engine();
}
// TODO(ctiller): re-evaluate this API
const grpc_call_context_element* legacy_context() const {
return DownCast<CallSpine*>(spine_.get())->legacy_context();
}
grpc_call_context_element* legacy_context() {
return DownCast<CallSpine*>(spine_.get())->legacy_context();
}

@ -175,12 +175,23 @@ class InterceptionChainBuilder final {
return *this;
};
// Add a filter that just mutates client initial metadata.
template <typename F>
void AddOnClientInitialMetadata(F f) {
stack_builder().AddOnClientInitialMetadata(std::move(f));
}
// Add a filter that just mutates server trailing metadata.
template <typename F>
void AddOnServerTrailingMetadata(F f) {
stack_builder().AddOnServerTrailingMetadata(std::move(f));
}
void Fail(absl::Status status) {
CHECK(!status.ok()) << status;
if (status_.ok()) status_ = std::move(status);
}
// Build this stack
absl::StatusOr<RefCountedPtr<UnstartedCallDestination>> Build(
FinalDestination final_destination);

@ -55,6 +55,7 @@
#include "src/core/lib/promise/pipe.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/call_destination.h"
#include "src/core/lib/transport/call_final_info.h"
#include "src/core/lib/transport/call_spine.h"
#include "src/core/lib/transport/connectivity_state.h"
@ -481,6 +482,15 @@ typedef struct grpc_transport_op {
grpc_handler_private_op_data handler_private;
} grpc_transport_op;
// Allocate a grpc_transport_op, and preconfigure the on_complete closure to
// \a on_complete and then delete the returned transport op
grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete);
// Allocate a grpc_transport_stream_op_batch, and preconfigure the on_complete
// closure
// to \a on_complete and then delete the returned transport op
grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
grpc_closure* on_complete);
void grpc_transport_stream_op_batch_finish_with_failure(
grpc_transport_stream_op_batch* batch, grpc_error_handle error,
grpc_core::CallCombiner* call_combiner);
@ -507,6 +517,21 @@ class Transport : public InternallyRefCounted<Transport> {
struct RawPointerChannelArgTag {};
static absl::string_view ChannelArgName() { return GRPC_ARG_TRANSPORT; }
// Though internally ref counted transports expose their "Ref" method to
// create a RefCountedPtr to themselves. The OrphanablePtr owner is the
// singleton decision maker on whether the transport should be destroyed or
// not.
// TODO(ctiller): consider moving to a DualRefCounted model (with the
// disadvantage that we would accidentally have many strong owners which is
// unnecessary for this type).
RefCountedPtr<Transport> Ref() {
return InternallyRefCounted<Transport>::Ref();
}
template <typename T>
RefCountedPtr<T> RefAsSubclass() {
return InternallyRefCounted<Transport>::RefAsSubclass<T>();
}
virtual FilterStackTransport* filter_stack_transport() = 0;
virtual ClientTransport* client_transport() = 0;
virtual ServerTransport* server_transport() = 0;
@ -527,6 +552,20 @@ class Transport : public InternallyRefCounted<Transport> {
// implementation of grpc_transport_perform_op
virtual void PerformOp(grpc_transport_op* op) = 0;
void StartConnectivityWatch(
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->start_connectivity_watch = std::move(watcher);
PerformOp(op);
}
void DisconnectWithError(grpc_error_handle error) {
CHECK(!error.ok()) << error;
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->disconnect_with_error = error;
PerformOp(op);
}
// implementation of grpc_transport_get_endpoint
virtual grpc_endpoint* GetEndpoint() = 0;
};
@ -582,24 +621,9 @@ class ClientTransport : public Transport {
class ServerTransport : public Transport {
public:
// Acceptor helps transports create calls.
class Acceptor {
public:
// Returns an arena that can be used to allocate memory for initial metadata
// parsing, and later passed to CreateCall() as the underlying arena for
// that call.
virtual Arena* CreateArena() = 0;
// Create a call at the server (or fail)
// arena must have been previously allocated by CreateArena()
virtual absl::StatusOr<CallInitiator> CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) = 0;
protected:
~Acceptor() = default;
};
// Called once slightly after transport setup to register the accept function.
virtual void SetAcceptor(Acceptor* acceptor) = 0;
virtual void SetCallDestination(
RefCountedPtr<UnstartedCallDestination> unstarted_call_handler) = 0;
protected:
~ServerTransport() override = default;
@ -607,15 +631,6 @@ class ServerTransport : public Transport {
} // namespace grpc_core
// Allocate a grpc_transport_op, and preconfigure the on_complete closure to
// \a on_complete and then delete the returned transport op
grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete);
// Allocate a grpc_transport_stream_op_batch, and preconfigure the on_complete
// closure
// to \a on_complete and then delete the returned transport op
grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
grpc_closure* on_complete);
namespace grpc_core {
// This is the key to be used for loading/storing keepalive_throttling in the
// absl::Status object.

@ -79,10 +79,11 @@ namespace {
void RegisterBuiltins(CoreConfiguration::Builder* builder) {
RegisterServerCallTracerFilter(builder);
builder->channel_init()
->RegisterFilter<LameClientFilter>(GRPC_CLIENT_LAME_CHANNEL)
->RegisterV2Filter<LameClientFilter>(GRPC_CLIENT_LAME_CHANNEL)
.Terminal();
builder->channel_init()
->RegisterFilter(GRPC_SERVER_CHANNEL, &Server::kServerTopFilter)
.SkipV3()
.BeforeAll();
}

@ -57,6 +57,7 @@
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/mpscq.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/pollset_set.h"
@ -81,6 +82,7 @@
#include "src/core/lib/surface/wait_for_cq_end_op.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/interception_chain.h"
namespace grpc_core {
@ -235,7 +237,8 @@ struct Server::RequestedCall {
template <typename OptionalPayload>
void Complete(OptionalPayload payload, ClientMetadata& md) {
Timestamp deadline = GetContext<Call>()->deadline();
Timestamp deadline =
md.get(GrpcTimeoutMetadata()).value_or(Timestamp::InfFuture());
switch (type) {
case RequestedCall::Type::BATCH_CALL:
CHECK(!payload.has_value());
@ -288,23 +291,29 @@ struct Server::RequestedCall {
// application to explicitly request RPCs and then matching those to incoming
// RPCs, along with a slow path by which incoming RPCs are put on a locked
// pending list if they aren't able to be matched to an application request.
class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
class Server::RealRequestMatcher : public RequestMatcherInterface {
public:
explicit RealRequestMatcherFilterStack(Server* server)
explicit RealRequestMatcher(Server* server)
: server_(server), requests_per_cq_(server->cqs_.size()) {}
~RealRequestMatcherFilterStack() override {
~RealRequestMatcher() override {
for (LockedMultiProducerSingleConsumerQueue& queue : requests_per_cq_) {
CHECK_EQ(queue.Pop(), nullptr);
}
CHECK(pending_.empty());
CHECK(pending_filter_stack_.empty());
CHECK(pending_promises_.empty());
}
void ZombifyPending() override {
while (!pending_.empty()) {
pending_.front().calld->SetState(CallData::CallState::ZOMBIED);
pending_.front().calld->KillZombie();
pending_.pop();
while (!pending_filter_stack_.empty()) {
pending_filter_stack_.front().calld->SetState(
CallData::CallState::ZOMBIED);
pending_filter_stack_.front().calld->KillZombie();
pending_filter_stack_.pop();
}
while (!pending_promises_.empty()) {
pending_promises_.front()->Finish(absl::InternalError("Server closed"));
pending_promises_.pop();
}
}
@ -329,35 +338,56 @@ class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
// matching calls
struct NextPendingCall {
RequestedCall* rc = nullptr;
CallData* pending;
CallData* pending_filter_stack = nullptr;
PendingCallPromises pending_promise;
};
while (true) {
NextPendingCall pending_call;
{
MutexLock lock(&server_->mu_call_);
while (!pending_.empty() &&
pending_.front().Age() > server_->max_time_in_pending_queue_) {
pending_.front().calld->SetState(CallData::CallState::ZOMBIED);
pending_.front().calld->KillZombie();
pending_.pop();
while (!pending_filter_stack_.empty() &&
pending_filter_stack_.front().Age() >
server_->max_time_in_pending_queue_) {
pending_filter_stack_.front().calld->SetState(
CallData::CallState::ZOMBIED);
pending_filter_stack_.front().calld->KillZombie();
pending_filter_stack_.pop();
}
if (!pending_.empty()) {
if (!pending_promises_.empty()) {
pending_call.rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[request_queue_index].Pop());
if (pending_call.rc != nullptr) {
pending_call.pending = pending_.front().calld;
pending_.pop();
pending_call.pending_promise =
std::move(pending_promises_.front());
pending_promises_.pop();
}
} else if (!pending_filter_stack_.empty()) {
pending_call.rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[request_queue_index].Pop());
if (pending_call.rc != nullptr) {
pending_call.pending_filter_stack =
pending_filter_stack_.front().calld;
pending_filter_stack_.pop();
}
}
}
if (pending_call.rc == nullptr) break;
if (!pending_call.pending->MaybeActivate()) {
// Zombied Call
pending_call.pending->KillZombie();
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
if (pending_call.pending_filter_stack != nullptr) {
if (!pending_call.pending_filter_stack->MaybeActivate()) {
// Zombied Call
pending_call.pending_filter_stack->KillZombie();
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
} else {
pending_call.pending_filter_stack->Publish(request_queue_index,
pending_call.rc);
}
} else {
pending_call.pending->Publish(request_queue_index, pending_call.rc);
if (!pending_call.pending_promise->Finish(
server(), request_queue_index, pending_call.rc)) {
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
}
}
}
}
@ -395,7 +425,7 @@ class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
}
if (rc == nullptr) {
calld->SetState(CallData::CallState::PENDING);
pending_.push(PendingCall{calld});
pending_filter_stack_.push(PendingCallFilterStack{calld});
return;
}
}
@ -403,91 +433,6 @@ class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
calld->Publish(cq_idx, rc);
}
ArenaPromise<absl::StatusOr<MatchResult>> MatchRequest(size_t) override {
Crash("not implemented for filter stack request matcher");
}
Server* server() const final { return server_; }
private:
Server* const server_;
struct PendingCall {
CallData* calld;
Timestamp created = Timestamp::Now();
Duration Age() { return Timestamp::Now() - created; }
};
std::queue<PendingCall> pending_;
std::vector<LockedMultiProducerSingleConsumerQueue> requests_per_cq_;
};
class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
public:
explicit RealRequestMatcherPromises(Server* server)
: server_(server), requests_per_cq_(server->cqs_.size()) {}
~RealRequestMatcherPromises() override {
for (LockedMultiProducerSingleConsumerQueue& queue : requests_per_cq_) {
CHECK_EQ(queue.Pop(), nullptr);
}
}
void ZombifyPending() override {
while (!pending_.empty()) {
pending_.front()->Finish(absl::InternalError("Server closed"));
pending_.pop();
}
}
void KillRequests(grpc_error_handle error) override {
for (size_t i = 0; i < requests_per_cq_.size(); i++) {
RequestedCall* rc;
while ((rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[i].Pop())) != nullptr) {
server_->FailCall(i, rc, error);
}
}
}
size_t request_queue_count() const override {
return requests_per_cq_.size();
}
void RequestCallWithPossiblePublish(size_t request_queue_index,
RequestedCall* call) override {
if (requests_per_cq_[request_queue_index].Push(&call->mpscq_node)) {
// this was the first queued request: we need to lock and start
// matching calls
struct NextPendingCall {
RequestedCall* rc = nullptr;
PendingCall pending;
};
while (true) {
NextPendingCall pending_call;
{
MutexLock lock(&server_->mu_call_);
if (!pending_.empty()) {
pending_call.rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[request_queue_index].Pop());
if (pending_call.rc != nullptr) {
pending_call.pending = std::move(pending_.front());
pending_.pop();
}
}
}
if (pending_call.rc == nullptr) break;
if (!pending_call.pending->Finish(server(), request_queue_index,
pending_call.rc)) {
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
}
}
}
}
void MatchOrQueue(size_t, CallData*) override {
Crash("not implemented for promises");
}
ArenaPromise<absl::StatusOr<MatchResult>> MatchRequest(
size_t start_request_queue_index) override {
for (size_t i = 0; i < requests_per_cq_.size(); i++) {
@ -509,10 +454,11 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
{
std::vector<std::shared_ptr<ActivityWaiter>> removed_pending;
MutexLock lock(&server_->mu_call_);
while (!pending_.empty() &&
pending_.front()->Age() > server_->max_time_in_pending_queue_) {
removed_pending.push_back(std::move(pending_.front()));
pending_.pop();
while (!pending_promises_.empty() &&
pending_promises_.front()->Age() >
server_->max_time_in_pending_queue_) {
removed_pending.push_back(std::move(pending_promises_.front()));
pending_promises_.pop();
}
for (loop_count = 0; loop_count < requests_per_cq_.size(); loop_count++) {
cq_idx =
@ -521,14 +467,14 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
if (rc != nullptr) break;
}
if (rc == nullptr) {
if (server_->pending_backlog_protector_.Reject(pending_.size(),
if (server_->pending_backlog_protector_.Reject(pending_promises_.size(),
server_->bitgen_)) {
return Immediate(absl::ResourceExhaustedError(
"Too many pending requests for this server"));
}
auto w = std::make_shared<ActivityWaiter>(
GetContext<Activity>()->MakeOwningWaker());
pending_.push(w);
pending_promises_.push(w);
return OnCancel(
[w]() -> Poll<absl::StatusOr<MatchResult>> {
std::unique_ptr<absl::StatusOr<MatchResult>> r(
@ -546,6 +492,11 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
private:
Server* const server_;
struct PendingCallFilterStack {
CallData* calld;
Timestamp created = Timestamp::Now();
Duration Age() { return Timestamp::Now() - created; }
};
struct ActivityWaiter {
using ResultType = absl::StatusOr<MatchResult>;
explicit ActivityWaiter(Waker waker) : waker(std::move(waker)) {}
@ -580,8 +531,9 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
std::atomic<ResultType*> result{nullptr};
const Timestamp created = Timestamp::Now();
};
using PendingCall = std::shared_ptr<ActivityWaiter>;
std::queue<PendingCall> pending_;
using PendingCallPromises = std::shared_ptr<ActivityWaiter>;
std::queue<PendingCallFilterStack> pending_filter_stack_;
std::queue<PendingCallPromises> pending_promises_;
std::vector<LockedMultiProducerSingleConsumerQueue> requests_per_cq_;
};
@ -784,13 +736,40 @@ class ChannelBroadcaster {
} // namespace
//
// Server::TransportConnectivityWatcher
//
class Server::TransportConnectivityWatcher
: public AsyncConnectivityStateWatcherInterface {
public:
TransportConnectivityWatcher(RefCountedPtr<ServerTransport> transport,
RefCountedPtr<Server> server)
: transport_(std::move(transport)), server_(std::move(server)) {}
private:
void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& /*status*/) override {
// Don't do anything until we are being shut down.
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
// Shut down channel.
MutexLock lock(&server_->mu_global_);
server_->connections_.erase(transport_.get());
--server_->connections_open_;
server_->MaybeFinishShutdown();
}
RefCountedPtr<ServerTransport> transport_;
RefCountedPtr<Server> server_;
};
//
// Server
//
const grpc_channel_filter Server::kServerTopFilter = {
Server::CallData::StartTransportStreamOpBatch,
Server::ChannelData::MakeCallPromise,
nullptr,
[](grpc_channel_element*, CallSpineInterface*) {
// TODO(ctiller): remove the server filter when call-v3 is finalized
},
@ -826,12 +805,91 @@ RefCountedPtr<channelz::ServerNode> CreateChannelzNode(
return channelz_node;
}
absl::StatusOr<ClientMetadataHandle> CheckClientMetadata(
ValueOrFailure<ClientMetadataHandle> md) {
if (!md.ok()) {
return absl::InternalError("Missing metadata");
}
if (!md.value()->get_pointer(HttpPathMetadata())) {
return absl::InternalError("Missing :path header");
}
if (!md.value()->get_pointer(HttpAuthorityMetadata())) {
return absl::InternalError("Missing :authority header");
}
return std::move(*md);
}
} // namespace
auto Server::MatchAndPublishCall(CallHandler call_handler) {
call_handler.SpawnGuarded("request_matcher", [this, call_handler]() mutable {
return TrySeq(
// Wait for initial metadata to pass through all filters
Map(call_handler.PullClientInitialMetadata(), CheckClientMetadata),
// Match request with requested call
[this, call_handler](ClientMetadataHandle md) mutable {
auto* registered_method = static_cast<RegisteredMethod*>(
md->get(GrpcRegisteredMethod()).value_or(nullptr));
RequestMatcherInterface* rm;
grpc_server_register_method_payload_handling payload_handling =
GRPC_SRM_PAYLOAD_NONE;
if (registered_method == nullptr) {
rm = unregistered_request_matcher_.get();
} else {
payload_handling = registered_method->payload_handling;
rm = registered_method->matcher.get();
}
auto maybe_read_first_message = If(
payload_handling == GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER,
[call_handler]() mutable { return call_handler.PullMessage(); },
[]() -> ValueOrFailure<absl::optional<MessageHandle>> {
return ValueOrFailure<absl::optional<MessageHandle>>(
absl::nullopt);
});
return TryJoin<absl::StatusOr>(
std::move(maybe_read_first_message), rm->MatchRequest(0),
[md = std::move(md)]() mutable {
return ValueOrFailure<ClientMetadataHandle>(std::move(md));
});
},
// Publish call to cq
[call_handler, this](std::tuple<absl::optional<MessageHandle>,
RequestMatcherInterface::MatchResult,
ClientMetadataHandle>
r) {
RequestMatcherInterface::MatchResult& mr = std::get<1>(r);
auto md = std::move(std::get<2>(r));
auto* rc = mr.TakeCall();
rc->Complete(std::move(std::get<0>(r)), *md);
grpc_call* call =
MakeServerCall(call_handler, std::move(md), this,
rc->cq_bound_to_call, rc->initial_metadata);
*rc->call = call;
return Map(WaitForCqEndOp(false, rc->tag, absl::OkStatus(), mr.cq()),
[rc = std::unique_ptr<RequestedCall>(rc)](Empty) {
return absl::OkStatus();
});
});
});
}
absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>
Server::MakeCallDestination(const ChannelArgs& args) {
InterceptionChainBuilder builder(args);
builder.AddOnClientInitialMetadata(
[this](ClientMetadata& md) { SetRegisteredMethodOnMetadata(md); });
CoreConfiguration::Get().channel_init().AddToInterceptionChainBuilder(
GRPC_SERVER_CHANNEL, builder);
return builder.Build(
MakeCallDestinationFromHandlerFunction([this](CallHandler handler) {
return MatchAndPublishCall(std::move(handler));
}));
}
Server::Server(const ChannelArgs& args)
: channel_args_(args),
channelz_node_(CreateChannelzNode(args)),
server_call_tracer_factory_(ServerCallTracerFactory::Get(args)),
compression_options_(CompressionOptionsFromChannelArgs(args)),
max_time_in_pending_queue_(Duration::Seconds(
channel_args_
.GetInt(GRPC_ARG_SERVER_MAX_UNREQUESTED_TIME_IN_SERVER_SECONDS)
@ -862,15 +920,6 @@ void Server::AddListener(OrphanablePtr<ListenerInterface> listener) {
}
void Server::Start() {
auto make_real_request_matcher =
[this]() -> std::unique_ptr<RequestMatcherInterface> {
if (IsPromiseBasedServerCallEnabled()) {
return std::make_unique<RealRequestMatcherPromises>(this);
} else {
return std::make_unique<RealRequestMatcherFilterStack>(this);
}
};
started_ = true;
for (grpc_completion_queue* cq : cqs_) {
if (grpc_cq_can_listen(cq)) {
@ -878,11 +927,11 @@ void Server::Start() {
}
}
if (unregistered_request_matcher_ == nullptr) {
unregistered_request_matcher_ = make_real_request_matcher();
unregistered_request_matcher_ = std::make_unique<RealRequestMatcher>(this);
}
for (auto& rm : registered_methods_) {
if (rm.second->matcher == nullptr) {
rm.second->matcher = make_real_request_matcher();
rm.second->matcher = std::make_unique<RealRequestMatcher>(this);
}
}
{
@ -913,37 +962,61 @@ grpc_error_handle Server::SetupTransport(
const RefCountedPtr<channelz::SocketNode>& socket_node) {
// Create channel.
global_stats().IncrementServerChannelsCreated();
absl::StatusOr<OrphanablePtr<Channel>> channel =
LegacyChannel::Create("", args.SetObject(transport), GRPC_SERVER_CHANNEL);
if (!channel.ok()) {
return absl_status_to_grpc_error(channel.status());
}
ChannelData* chand = static_cast<ChannelData*>(
grpc_channel_stack_element((*channel)->channel_stack(), 0)->channel_data);
// Set up CQs.
size_t cq_idx;
for (cq_idx = 0; cq_idx < cqs_.size(); cq_idx++) {
if (grpc_cq_pollset(cqs_[cq_idx]) == accepting_pollset) break;
}
if (cq_idx == cqs_.size()) {
// Completion queue not found. Pick a random one to publish new calls to.
cq_idx = static_cast<size_t>(rand()) % std::max<size_t>(1, cqs_.size());
}
// Set up channelz node.
intptr_t channelz_socket_uuid = 0;
if (socket_node != nullptr) {
channelz_socket_uuid = socket_node->uuid();
channelz_node_->AddChildSocket(socket_node);
}
// Initialize chand.
chand->InitTransport(Ref(), std::move(*channel), cq_idx, transport,
channelz_socket_uuid);
if (transport->server_transport() != nullptr) {
// Take ownership
// TODO(ctiller): post-v3-transition make this method take an
// OrphanablePtr<ServerTransport> directly.
OrphanablePtr<ServerTransport> t(transport->server_transport());
auto destination = MakeCallDestination(args.SetObject(transport));
if (!destination.ok()) {
return absl_status_to_grpc_error(destination.status());
}
// TODO(ctiller): add channelz node
t->SetCallDestination(std::move(*destination));
MutexLock lock(&mu_global_);
if (ShutdownCalled()) {
t->DisconnectWithError(GRPC_ERROR_CREATE("Server shutdown"));
}
t->StartConnectivityWatch(MakeOrphanable<TransportConnectivityWatcher>(
t->RefAsSubclass<ServerTransport>(), Ref()));
gpr_log(GPR_INFO, "Adding connection");
connections_.emplace(std::move(t));
++connections_open_;
} else {
CHECK(transport->filter_stack_transport() != nullptr);
absl::StatusOr<OrphanablePtr<Channel>> channel = LegacyChannel::Create(
"", args.SetObject(transport), GRPC_SERVER_CHANNEL);
if (!channel.ok()) {
return absl_status_to_grpc_error(channel.status());
}
ChannelData* chand = static_cast<ChannelData*>(
grpc_channel_stack_element((*channel)->channel_stack(), 0)
->channel_data);
// Set up CQs.
size_t cq_idx;
for (cq_idx = 0; cq_idx < cqs_.size(); cq_idx++) {
if (grpc_cq_pollset(cqs_[cq_idx]) == accepting_pollset) break;
}
if (cq_idx == cqs_.size()) {
// Completion queue not found. Pick a random one to publish new calls to.
cq_idx = static_cast<size_t>(rand()) % std::max<size_t>(1, cqs_.size());
}
intptr_t channelz_socket_uuid = 0;
if (socket_node != nullptr) {
channelz_socket_uuid = socket_node->uuid();
channelz_node_->AddChildSocket(socket_node);
}
// Initialize chand.
chand->InitTransport(Ref(), std::move(*channel), cq_idx, transport,
channelz_socket_uuid);
}
return absl::OkStatus();
}
bool Server::HasOpenConnections() {
MutexLock lock(&mu_global_);
return !channels_.empty();
return !channels_.empty() || !connections_.empty();
}
void Server::SetRegisteredMethodAllocator(
@ -1023,16 +1096,18 @@ void Server::MaybeFinishShutdown() {
MutexLock lock(&mu_call_);
KillPendingWorkLocked(GRPC_ERROR_CREATE("Server Shutdown"));
}
if (!channels_.empty() || listeners_destroyed_ < listeners_.size()) {
if (!channels_.empty() || connections_open_ > 0 ||
listeners_destroyed_ < listeners_.size()) {
if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME),
last_shutdown_message_time_),
gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
last_shutdown_message_time_ = gpr_now(GPR_CLOCK_REALTIME);
gpr_log(GPR_DEBUG,
"Waiting for %" PRIuPTR " channels and %" PRIuPTR "/%" PRIuPTR
"Waiting for %" PRIuPTR " channels %" PRIuPTR
" connections and %" PRIuPTR "/%" PRIuPTR
" listeners to be destroyed before shutting down server",
channels_.size(), listeners_.size() - listeners_destroyed_,
listeners_.size());
channels_.size(), connections_open_,
listeners_.size() - listeners_destroyed_, listeners_.size());
}
return;
}
@ -1095,6 +1170,7 @@ void DonePublishedShutdown(void* /*done_arg*/, grpc_cq_completion* storage) {
// -- Once there are no more calls in progress, the channel is closed.
void Server::ShutdownAndNotify(grpc_completion_queue* cq, void* tag) {
ChannelBroadcaster broadcaster;
absl::flat_hash_set<OrphanablePtr<ServerTransport>> removing_connections;
{
// Wait for startup to be finished. Locks mu_global.
MutexLock lock(&mu_global_);
@ -1114,6 +1190,7 @@ void Server::ShutdownAndNotify(grpc_completion_queue* cq, void* tag) {
}
last_shutdown_message_time_ = gpr_now(GPR_CLOCK_REALTIME);
broadcaster.FillChannelsLocked(GetChannelsLocked());
removing_connections.swap(connections_);
// Collect all unregistered then registered calls.
{
MutexLock lock(&mu_call_);
@ -1300,17 +1377,6 @@ Server::ChannelData::~ChannelData() {
}
}
Arena* Server::ChannelData::CreateArena() { return channel_->CreateArena(); }
absl::StatusOr<CallInitiator> Server::ChannelData::CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) {
SetRegisteredMethodOnMetadata(*client_initial_metadata);
auto call = MakeServerCall(std::move(client_initial_metadata), server_.get(),
channel_.get(), arena);
InitCall(call);
return CallInitiator(std::move(call));
}
void Server::ChannelData::InitTransport(RefCountedPtr<Server> server,
OrphanablePtr<Channel> channel,
size_t cq_idx, Transport* transport,
@ -1327,22 +1393,15 @@ void Server::ChannelData::InitTransport(RefCountedPtr<Server> server,
}
// Start accept_stream transport op.
grpc_transport_op* op = grpc_make_transport_op(nullptr);
int accept_stream_types = 0;
if (transport->filter_stack_transport() != nullptr) {
++accept_stream_types;
op->set_accept_stream = true;
op->set_accept_stream_fn = AcceptStream;
op->set_registered_method_matcher_fn = [](void* arg,
ClientMetadata* metadata) {
static_cast<ChannelData*>(arg)->SetRegisteredMethodOnMetadata(*metadata);
};
op->set_accept_stream_user_data = this;
}
if (transport->server_transport() != nullptr) {
++accept_stream_types;
transport->server_transport()->SetAcceptor(this);
}
CHECK_EQ(accept_stream_types, 1);
CHECK(transport->filter_stack_transport() != nullptr);
op->set_accept_stream = true;
op->set_accept_stream_fn = AcceptStream;
op->set_registered_method_matcher_fn = [](void* arg,
ClientMetadata* metadata) {
static_cast<ChannelData*>(arg)->server_->SetRegisteredMethodOnMetadata(
*metadata);
};
op->set_accept_stream_user_data = this;
op->start_connectivity_watch = MakeOrphanable<ConnectivityWatcher>(this);
if (server_->ShutdownCalled()) {
op->disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown");
@ -1350,24 +1409,23 @@ void Server::ChannelData::InitTransport(RefCountedPtr<Server> server,
transport->PerformOp(op);
}
Server::RegisteredMethod* Server::ChannelData::GetRegisteredMethod(
Server::RegisteredMethod* Server::GetRegisteredMethod(
const absl::string_view& host, const absl::string_view& path) {
if (server_->registered_methods_.empty()) return nullptr;
if (registered_methods_.empty()) return nullptr;
// check for an exact match with host
auto it = server_->registered_methods_.find(std::make_pair(host, path));
if (it != server_->registered_methods_.end()) {
auto it = registered_methods_.find(std::make_pair(host, path));
if (it != registered_methods_.end()) {
return it->second.get();
}
// check for wildcard method definition (no host set)
it = server_->registered_methods_.find(std::make_pair("", path));
if (it != server_->registered_methods_.end()) {
it = registered_methods_.find(std::make_pair("", path));
if (it != registered_methods_.end()) {
return it->second.get();
}
return nullptr;
}
void Server::ChannelData::SetRegisteredMethodOnMetadata(
ClientMetadata& metadata) {
void Server::SetRegisteredMethodOnMetadata(ClientMetadata& metadata) {
auto* authority = metadata.get_pointer(HttpAuthorityMetadata());
if (authority == nullptr) {
authority = metadata.get_pointer(HostMetadata());
@ -1403,188 +1461,14 @@ void Server::ChannelData::AcceptStream(void* arg, Transport* /*transport*/,
grpc_call* call;
grpc_error_handle error = grpc_call_create(&args, &call);
grpc_call_stack* call_stack = grpc_call_get_call_stack(call);
if (call_stack == nullptr) { // Promise based calls do not have a call stack
CHECK(error.ok());
CHECK(IsPromiseBasedServerCallEnabled());
CHECK_NE(call_stack, nullptr);
grpc_call_element* elem = grpc_call_stack_element(call_stack, 0);
auto* calld = static_cast<Server::CallData*>(elem->call_data);
if (!error.ok()) {
calld->FailCallCreation();
return;
} else {
grpc_call_element* elem = grpc_call_stack_element(call_stack, 0);
auto* calld = static_cast<Server::CallData*>(elem->call_data);
if (!error.ok()) {
calld->FailCallCreation();
return;
}
calld->Start(elem);
}
}
namespace {
auto CancelledDueToServerShutdown() {
return [] {
return ServerMetadataFromStatus(absl::CancelledError("Server shutdown"));
};
}
} // namespace
void Server::ChannelData::InitCall(RefCountedPtr<CallSpineInterface> call) {
call->SpawnGuarded("request_matcher", [this, call]() {
return TrySeq(
// Wait for initial metadata to pass through all filters
Map(call->PullClientInitialMetadata(),
[](ValueOrFailure<ClientMetadataHandle> md)
-> absl::StatusOr<ClientMetadataHandle> {
if (!md.ok()) {
return absl::InternalError("Missing metadata");
}
if (!md.value()->get_pointer(HttpPathMetadata())) {
return absl::InternalError("Missing :path header");
}
if (!md.value()->get_pointer(HttpAuthorityMetadata())) {
return absl::InternalError("Missing :authority header");
}
return std::move(*md);
}),
// Match request with requested call
[this, call](ClientMetadataHandle md) {
auto* registered_method = static_cast<RegisteredMethod*>(
md->get(GrpcRegisteredMethod()).value_or(nullptr));
RequestMatcherInterface* rm;
grpc_server_register_method_payload_handling payload_handling =
GRPC_SRM_PAYLOAD_NONE;
if (registered_method == nullptr) {
rm = server_->unregistered_request_matcher_.get();
} else {
payload_handling = registered_method->payload_handling;
rm = registered_method->matcher.get();
}
auto maybe_read_first_message = If(
payload_handling == GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER,
[call]() { return call->PullClientToServerMessage(); },
[]() -> ValueOrFailure<absl::optional<MessageHandle>> {
return ValueOrFailure<absl::optional<MessageHandle>>(
absl::nullopt);
});
return TryJoin<absl::StatusOr>(
std::move(maybe_read_first_message), rm->MatchRequest(cq_idx()),
[md = std::move(md)]() mutable {
return ValueOrFailure<ClientMetadataHandle>(std::move(md));
});
},
// Publish call to cq
[](std::tuple<absl::optional<MessageHandle>,
RequestMatcherInterface::MatchResult,
ClientMetadataHandle>
r) {
RequestMatcherInterface::MatchResult& mr = std::get<1>(r);
auto md = std::move(std::get<2>(r));
auto* rc = mr.TakeCall();
rc->Complete(std::move(std::get<0>(r)), *md);
auto* call_context = GetContext<CallContext>();
const auto* deadline = md->get_pointer(GrpcTimeoutMetadata());
if (deadline != nullptr) {
GetContext<Call>()->UpdateDeadline(*deadline);
}
*rc->call = call_context->c_call();
grpc_call_ref(*rc->call);
grpc_call_set_completion_queue(call_context->c_call(),
rc->cq_bound_to_call);
call_context->server_call_context()->PublishInitialMetadata(
std::move(md), rc->initial_metadata);
// TODO(ctiller): publish metadata
return Map(WaitForCqEndOp(false, rc->tag, absl::OkStatus(), mr.cq()),
[rc = std::unique_ptr<RequestedCall>(rc)](Empty) {
return absl::OkStatus();
});
});
});
}
ArenaPromise<ServerMetadataHandle> Server::ChannelData::MakeCallPromise(
grpc_channel_element* elem, CallArgs call_args, NextPromiseFactory) {
auto* chand = static_cast<Server::ChannelData*>(elem->channel_data);
auto* server = chand->server_.get();
if (server->ShutdownCalled()) return CancelledDueToServerShutdown();
auto cleanup_ref =
absl::MakeCleanup([server] { server->ShutdownUnrefOnRequest(); });
if (!server->ShutdownRefOnRequest()) return CancelledDueToServerShutdown();
auto path_ptr =
call_args.client_initial_metadata->get_pointer(HttpPathMetadata());
if (path_ptr == nullptr) {
return [] {
return ServerMetadataFromStatus(
absl::InternalError("Missing :path header"));
};
}
auto host_ptr =
call_args.client_initial_metadata->get_pointer(HttpAuthorityMetadata());
if (host_ptr == nullptr) {
return [] {
return ServerMetadataFromStatus(
absl::InternalError("Missing :authority header"));
};
}
// Find request matcher.
RequestMatcherInterface* matcher;
RegisteredMethod* rm = static_cast<RegisteredMethod*>(
call_args.client_initial_metadata->get(GrpcRegisteredMethod())
.value_or(nullptr));
ArenaPromise<absl::StatusOr<NextResult<MessageHandle>>>
maybe_read_first_message([] { return NextResult<MessageHandle>(); });
if (rm != nullptr) {
matcher = rm->matcher.get();
switch (rm->payload_handling) {
case GRPC_SRM_PAYLOAD_NONE:
break;
case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER:
maybe_read_first_message =
Map(call_args.client_to_server_messages->Next(),
[](NextResult<MessageHandle> msg)
-> absl::StatusOr<NextResult<MessageHandle>> {
return std::move(msg);
});
}
} else {
matcher = server->unregistered_request_matcher_.get();
}
return TrySeq(
std::move(maybe_read_first_message),
[cleanup_ref = std::move(cleanup_ref), matcher,
chand](NextResult<MessageHandle> payload) mutable {
return Map(
[cleanup_ref = std::move(cleanup_ref),
mr = matcher->MatchRequest(chand->cq_idx())]() mutable {
return mr();
},
[payload = std::move(payload)](
absl::StatusOr<RequestMatcherInterface::MatchResult> mr) mutable
-> absl::StatusOr<std::pair<RequestMatcherInterface::MatchResult,
NextResult<MessageHandle>>> {
if (!mr.ok()) return mr.status();
return std::make_pair(std::move(*mr), std::move(payload));
});
},
[call_args =
std::move(call_args)](std::pair<RequestMatcherInterface::MatchResult,
NextResult<MessageHandle>>
r) mutable {
auto& mr = r.first;
auto& payload = r.second;
auto* rc = mr.TakeCall();
auto* cq_for_new_request = mr.cq();
auto* server_call_context =
GetContext<CallContext>()->server_call_context();
rc->Complete(std::move(payload), *call_args.client_initial_metadata);
server_call_context->PublishInitialMetadata(
std::move(call_args.client_initial_metadata), rc->initial_metadata);
return server_call_context->MakeTopOfServerCallPromise(
std::move(call_args), rc->cq_bound_to_call,
[rc, cq_for_new_request](grpc_call* call) {
*rc->call = call;
grpc_cq_end_op(cq_for_new_request, rc->tag, absl::OkStatus(),
Server::DoneRequestEvent, rc, &rc->completion,
true);
});
});
calld->Start(elem);
}
void Server::ChannelData::FinishDestroy(void* arg,

@ -38,6 +38,7 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/passive_listener.h>
#include <grpc/slice.h>
@ -215,6 +216,10 @@ class Server : public ServerInterface,
void SendGoaways() ABSL_LOCKS_EXCLUDED(mu_global_, mu_call_);
grpc_compression_options compression_options() const override {
return compression_options_;
}
private:
// note: the grpc_core::Server redundant namespace qualification is
// required for older gcc versions.
@ -227,13 +232,12 @@ class Server : public ServerInterface,
struct RequestedCall;
class RequestMatcherInterface;
class RealRequestMatcherFilterStack;
class RealRequestMatcherPromises;
class RealRequestMatcher;
class AllocatingRequestMatcherBase;
class AllocatingRequestMatcherBatch;
class AllocatingRequestMatcherRegistered;
class ChannelData final : public ServerTransport::Acceptor {
class ChannelData final {
public:
ChannelData() = default;
~ChannelData();
@ -246,26 +250,17 @@ class Server : public ServerInterface,
Channel* channel() const { return channel_.get(); }
size_t cq_idx() const { return cq_idx_; }
RegisteredMethod* GetRegisteredMethod(const absl::string_view& host,
const absl::string_view& path);
// Filter vtable functions.
static grpc_error_handle InitChannelElement(
grpc_channel_element* elem, grpc_channel_element_args* args);
static void DestroyChannelElement(grpc_channel_element* elem);
static ArenaPromise<ServerMetadataHandle> MakeCallPromise(
grpc_channel_element* elem, CallArgs call_args, NextPromiseFactory);
void InitCall(RefCountedPtr<CallSpineInterface> call);
Arena* CreateArena() override;
absl::StatusOr<CallInitiator> CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) override;
private:
class ConnectivityWatcher;
static void AcceptStream(void* arg, Transport* /*transport*/,
const void* transport_server_data);
void SetRegisteredMethodOnMetadata(ClientMetadata& metadata);
void Destroy() ABSL_EXCLUSIVE_LOCKS_REQUIRED(server_->mu_global_);
@ -396,6 +391,12 @@ class Server : public ServerInterface,
using is_transparent = void;
};
class TransportConnectivityWatcher;
RegisteredMethod* GetRegisteredMethod(const absl::string_view& host,
const absl::string_view& path);
void SetRegisteredMethodOnMetadata(ClientMetadata& metadata);
static void ListenerDestroyDone(void* arg, grpc_error_handle error);
static void DoneShutdownEvent(void* server,
@ -457,6 +458,10 @@ class Server : public ServerInterface,
return shutdown_refs_.load(std::memory_order_acquire) == 0;
}
auto MatchAndPublishCall(CallHandler call_handler);
absl::StatusOr<RefCountedPtr<UnstartedCallDestination>> MakeCallDestination(
const ChannelArgs& args);
ChannelArgs const channel_args_;
RefCountedPtr<channelz::ServerNode> channelz_node_;
std::unique_ptr<grpc_server_config_fetcher> config_fetcher_;
@ -465,6 +470,7 @@ class Server : public ServerInterface,
std::vector<grpc_completion_queue*> cqs_;
std::vector<grpc_pollset*> pollsets_;
bool started_ = false;
const grpc_compression_options compression_options_;
// The two following mutexes control access to server-state.
// mu_global_ controls access to non-call-related state (e.g., channel state).
@ -512,6 +518,9 @@ class Server : public ServerInterface,
absl::BitGen bitgen_ ABSL_GUARDED_BY(mu_call_);
std::list<ChannelData*> channels_;
absl::flat_hash_set<OrphanablePtr<ServerTransport>> connections_
ABSL_GUARDED_BY(mu_global_);
size_t connections_open_ ABSL_GUARDED_BY(mu_global_) = 0;
std::list<Listener> listeners_;
size_t listeners_destroyed_ = 0;

@ -17,6 +17,7 @@
#ifndef GRPC_SRC_CORE_SERVER_SERVER_INTERFACE_H
#define GRPC_SRC_CORE_SERVER_SERVER_INTERFACE_H
#include <grpc/impl/compression_types.h>
#include <grpc/support/port_platform.h>
#include "src/core/channelz/channelz.h"
@ -36,6 +37,7 @@ class ServerInterface {
virtual const ChannelArgs& channel_args() const = 0;
virtual channelz::ServerNode* channelz_node() const = 0;
virtual ServerCallTracerFactory* server_call_tracer_factory() const = 0;
virtual grpc_compression_options compression_options() const = 0;
};
} // namespace grpc_core

@ -46,6 +46,7 @@
#include <openssl/x509v3.h>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@ -53,7 +54,6 @@
#include <grpc/grpc_crl_provider.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd_id.h>
@ -204,7 +204,7 @@ static void init_openssl(void) {
CRYPTO_set_locking_callback(openssl_locking_cb);
CRYPTO_set_id_callback(openssl_thread_id_cb);
} else {
gpr_log(GPR_INFO, "OpenSSL callback has already been set.");
LOG(INFO) << "OpenSSL callback has already been set.";
}
#endif
g_ssl_ctx_ex_factory_index =
@ -234,7 +234,7 @@ static void ssl_log_where_info(const SSL* ssl, int where, int flag,
// Used for debugging. TODO(jboeuf): Remove when code is mature enough.
static void ssl_info_callback(const SSL* ssl, int where, int ret) {
if (ret == 0) {
gpr_log(GPR_ERROR, "ssl_info_callback: error occurred.\n");
LOG(ERROR) << "ssl_info_callback: error occurred.\n";
return;
}
@ -277,19 +277,18 @@ static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8,
X509_NAME* subject_name = X509_get_subject_name(cert);
int utf8_returned_size = 0;
if (subject_name == nullptr) {
gpr_log(GPR_DEBUG, "Could not get subject name from certificate.");
VLOG(2) << "Could not get subject name from certificate.";
return TSI_NOT_FOUND;
}
common_name_index =
X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
if (common_name_index == -1) {
gpr_log(GPR_DEBUG,
"Could not get common name of subject from certificate.");
VLOG(2) << "Could not get common name of subject from certificate.";
return TSI_NOT_FOUND;
}
common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
if (common_name_entry == nullptr) {
gpr_log(GPR_ERROR, "Could not get common name entry from certificate.");
LOG(ERROR) << "Could not get common name entry from certificate.";
return TSI_INTERNAL_ERROR;
}
common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
@ -300,7 +299,7 @@ static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8,
}
utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
if (utf8_returned_size < 0) {
gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string.");
LOG(ERROR) << "Could not extract utf8 from asn1 string.";
return TSI_OUT_OF_RESOURCES;
}
*utf8_size = static_cast<size_t>(utf8_returned_size);
@ -336,7 +335,7 @@ static tsi_result peer_property_from_x509_subject(X509* cert,
bool is_verified_root_cert) {
X509_NAME* subject_name = X509_get_subject_name(cert);
if (subject_name == nullptr) {
gpr_log(GPR_INFO, "Could not get subject name from certificate.");
LOG(INFO) << "Could not get subject name from certificate.";
return TSI_NOT_FOUND;
}
BIO* bio = BIO_new(BIO_s_mem());
@ -344,7 +343,7 @@ static tsi_result peer_property_from_x509_subject(X509* cert,
char* contents;
long len = BIO_get_mem_data(bio, &contents);
if (len < 0) {
gpr_log(GPR_ERROR, "Could not get subject entry from certificate.");
LOG(ERROR) << "Could not get subject entry from certificate.";
BIO_free(bio);
return TSI_INTERNAL_ERROR;
}
@ -409,7 +408,7 @@ static tsi_result add_subject_alt_names_properties_to_peer(
property_name = TSI_X509_URI_PEER_PROPERTY;
}
if (name_size < 0) {
gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
LOG(ERROR) << "Could not get utf8 from asn1 string.";
result = TSI_INTERNAL_ERROR;
break;
}
@ -435,14 +434,14 @@ static tsi_result add_subject_alt_names_properties_to_peer(
} else if (subject_alt_name->d.iPAddress->length == 16) {
af = AF_INET6;
} else {
gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP");
LOG(ERROR) << "SAN IP Address contained invalid IP";
result = TSI_INTERNAL_ERROR;
break;
}
const char* name = inet_ntop(af, subject_alt_name->d.iPAddress->data,
ntop_buf, INET6_ADDRSTRLEN);
if (name == nullptr) {
gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet.");
LOG(ERROR) << "Could not get IP string from asn1 octet.";
result = TSI_INTERNAL_ERROR;
break;
}
@ -605,7 +604,7 @@ static tsi_result ssl_ctx_use_engine_private_key(SSL_CTX* context,
}
engine_name = static_cast<char*>(gpr_zalloc(engine_name_length + 1));
memcpy(engine_name, engine_start, engine_name_length);
gpr_log(GPR_DEBUG, "ENGINE key: %s", engine_name);
VLOG(2) << "ENGINE key: " << engine_name;
ENGINE_load_dynamic();
engine = ENGINE_by_id(engine_name);
if (engine == nullptr) {
@ -613,7 +612,7 @@ static tsi_result ssl_ctx_use_engine_private_key(SSL_CTX* context,
// current working directory.
engine = ENGINE_by_id("dynamic");
if (engine == nullptr) {
gpr_log(GPR_ERROR, "Cannot load dynamic engine");
LOG(ERROR) << "Cannot load dynamic engine";
result = TSI_INVALID_ARGUMENT;
break;
}
@ -622,29 +621,29 @@ static tsi_result ssl_ctx_use_engine_private_key(SSL_CTX* context,
!ENGINE_ctrl_cmd_string(engine, "DIR_ADD", ".", 0) ||
!ENGINE_ctrl_cmd_string(engine, "LIST_ADD", "1", 0) ||
!ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) {
gpr_log(GPR_ERROR, "Cannot find engine");
LOG(ERROR) << "Cannot find engine";
result = TSI_INVALID_ARGUMENT;
break;
}
}
if (!ENGINE_set_default(engine, ENGINE_METHOD_ALL)) {
gpr_log(GPR_ERROR, "ENGINE_set_default with ENGINE_METHOD_ALL failed");
LOG(ERROR) << "ENGINE_set_default with ENGINE_METHOD_ALL failed";
result = TSI_INVALID_ARGUMENT;
break;
}
if (!ENGINE_init(engine)) {
gpr_log(GPR_ERROR, "ENGINE_init failed");
LOG(ERROR) << "ENGINE_init failed";
result = TSI_INVALID_ARGUMENT;
break;
}
private_key = ENGINE_load_private_key(engine, key_id, 0, 0);
if (private_key == nullptr) {
gpr_log(GPR_ERROR, "ENGINE_load_private_key failed");
LOG(ERROR) << "ENGINE_load_private_key failed";
result = TSI_INVALID_ARGUMENT;
break;
}
if (!SSL_CTX_use_PrivateKey(context, private_key)) {
gpr_log(GPR_ERROR, "SSL_CTX_use_PrivateKey failed");
LOG(ERROR) << "SSL_CTX_use_PrivateKey failed";
result = TSI_INVALID_ARGUMENT;
break;
}
@ -725,7 +724,7 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store,
if (root_names != nullptr) {
root_name = X509_get_subject_name(root);
if (root_name == nullptr) {
gpr_log(GPR_ERROR, "Could not get name from root certificate.");
LOG(ERROR) << "Could not get name from root certificate.";
result = TSI_INVALID_ARGUMENT;
break;
}
@ -742,7 +741,7 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store,
unsigned long error = ERR_get_error();
if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
LOG(ERROR) << "Could not add root certificate to ssl context.";
result = TSI_INTERNAL_ERROR;
break;
}
@ -751,7 +750,7 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store,
num_roots++;
}
if (num_roots == 0) {
gpr_log(GPR_ERROR, "Could not load any root certificate.");
LOG(ERROR) << "Could not load any root certificate.";
result = TSI_INVALID_ARGUMENT;
}
@ -790,7 +789,7 @@ static tsi_result populate_ssl_context(
result = ssl_ctx_use_certificate_chain(context, key_cert_pair->cert_chain,
strlen(key_cert_pair->cert_chain));
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Invalid cert chain file.");
LOG(ERROR) << "Invalid cert chain file.";
return result;
}
}
@ -798,7 +797,7 @@ static tsi_result populate_ssl_context(
result = ssl_ctx_use_private_key(context, key_cert_pair->private_key,
strlen(key_cert_pair->private_key));
if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
gpr_log(GPR_ERROR, "Invalid private key.");
LOG(ERROR) << "Invalid private key.";
return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
}
}
@ -812,7 +811,7 @@ static tsi_result populate_ssl_context(
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
LOG(ERROR) << "Could not set ephemeral ECDH key.";
EC_KEY_free(ecdh);
return TSI_INTERNAL_ERROR;
}
@ -820,7 +819,7 @@ static tsi_result populate_ssl_context(
EC_KEY_free(ecdh);
#else
if (!SSL_CTX_set1_groups(context, kSslEcCurveNames, 1)) {
gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
LOG(ERROR) << "Could not set ephemeral ECDH key.";
return TSI_INTERNAL_ERROR;
}
SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
@ -840,7 +839,7 @@ tsi_result tsi_ssl_extract_x509_subject_names_from_pem_cert(
cert = PEM_read_bio_X509(pem, nullptr, nullptr, const_cast<char*>(""));
if (cert == nullptr) {
gpr_log(GPR_ERROR, "Invalid certificate");
LOG(ERROR) << "Invalid certificate";
result = TSI_INVALID_ARGUMENT;
} else {
result = peer_from_x509(cert, 0, peer);
@ -962,7 +961,7 @@ static int RootCertExtractCallback(X509_STORE_CTX* ctx, void* /*arg*/) {
int success =
SSL_set_ex_data(ssl, g_ssl_ex_verified_root_cert_index, root_cert);
if (success == 0) {
gpr_log(GPR_INFO, "Could not set verified root cert in SSL's ex_data");
LOG(INFO) << "Could not set verified root cert in SSL's ex_data";
} else {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
X509_up_ref(root_cert);
@ -1007,13 +1006,13 @@ static absl::StatusOr<X509_CRL*> GetCrlFromProvider(
}
absl::StatusOr<std::string> issuer_name = grpc_core::IssuerFromCert(cert);
if (!issuer_name.ok()) {
gpr_log(GPR_INFO, "Could not get certificate issuer name");
LOG(INFO) << "Could not get certificate issuer name";
return absl::InvalidArgumentError(issuer_name.status().message());
}
absl::StatusOr<std::string> akid = grpc_core::AkidFromCertificate(cert);
std::string akid_to_use;
if (!akid.ok()) {
gpr_log(GPR_INFO, "Could not get certificate authority key identifier.");
LOG(INFO) << "Could not get certificate authority key identifier.";
} else {
akid_to_use = *akid;
}
@ -1046,12 +1045,12 @@ static bool ValidateCrl(X509* cert, X509* issuer, X509_CRL* crl) {
// 6.3.3b verify issuer and scope
valid = grpc_core::VerifyCrlCertIssuerNamesMatch(crl, cert);
if (!valid) {
gpr_log(GPR_DEBUG, "CRL and cert issuer names mismatched.");
VLOG(2) << "CRL and cert issuer names mismatched.";
return valid;
}
valid = grpc_core::HasCrlSignBit(issuer);
if (!valid) {
gpr_log(GPR_DEBUG, "CRL issuer not allowed to sign CRLs.");
VLOG(2) << "CRL issuer not allowed to sign CRLs.";
return valid;
}
// 6.3.3c Not supporting deltas
@ -1062,7 +1061,7 @@ static bool ValidateCrl(X509* cert, X509* issuer, X509_CRL* crl) {
// 6.3.3g Verify CRL Signature
valid = grpc_core::VerifyCrlSignature(crl, issuer);
if (!valid) {
gpr_log(GPR_DEBUG, "Crl signature check failed.");
VLOG(2) << "Crl signature check failed.";
}
return valid;
}
@ -1152,7 +1151,7 @@ static int CheckChainRevocation(
static int CustomVerificationFunction(X509_STORE_CTX* ctx, void* arg) {
int ret = X509_verify_cert(ctx);
if (ret <= 0) {
gpr_log(GPR_DEBUG, "Failed to verify cert chain.");
VLOG(2) << "Failed to verify cert chain.";
// Verification failed. We shouldn't expect to have a verified chain, so
// there is no need to attempt to extract the root cert from it, check for
// revocation, or check anything else.
@ -1162,7 +1161,7 @@ static int CustomVerificationFunction(X509_STORE_CTX* ctx, void* arg) {
if (provider != nullptr) {
ret = CheckChainRevocation(ctx, provider);
if (ret <= 0) {
gpr_log(GPR_DEBUG, "The chain failed revocation checks.");
VLOG(2) << "The chain failed revocation checks.";
return ret;
}
}
@ -1198,7 +1197,7 @@ static tsi_result tsi_set_min_and_max_tls_versions(
break;
#endif
default:
gpr_log(GPR_INFO, "TLS version is not supported.");
LOG(INFO) << "TLS version is not supported.";
return TSI_FAILED_PRECONDITION;
}
@ -1217,7 +1216,7 @@ static tsi_result tsi_set_min_and_max_tls_versions(
#endif
break;
default:
gpr_log(GPR_INFO, "TLS version is not supported.");
LOG(INFO) << "TLS version is not supported.";
return TSI_FAILED_PRECONDITION;
}
#endif
@ -1229,25 +1228,25 @@ static tsi_result tsi_set_min_and_max_tls_versions(
tsi_ssl_root_certs_store* tsi_ssl_root_certs_store_create(
const char* pem_roots) {
if (pem_roots == nullptr) {
gpr_log(GPR_ERROR, "The root certificates are empty.");
LOG(ERROR) << "The root certificates are empty.";
return nullptr;
}
tsi_ssl_root_certs_store* root_store = static_cast<tsi_ssl_root_certs_store*>(
gpr_zalloc(sizeof(tsi_ssl_root_certs_store)));
if (root_store == nullptr) {
gpr_log(GPR_ERROR, "Could not allocate buffer for ssl_root_certs_store.");
LOG(ERROR) << "Could not allocate buffer for ssl_root_certs_store.";
return nullptr;
}
root_store->store = X509_STORE_new();
if (root_store->store == nullptr) {
gpr_log(GPR_ERROR, "Could not allocate buffer for X509_STORE.");
LOG(ERROR) << "Could not allocate buffer for X509_STORE.";
gpr_free(root_store);
return nullptr;
}
tsi_result result = x509_store_load_certs(root_store->store, pem_roots,
strlen(pem_roots), nullptr);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Could not load root certificates.");
LOG(ERROR) << "Could not load root certificates.";
X509_STORE_free(root_store->store);
gpr_free(root_store);
return nullptr;
@ -1477,9 +1476,8 @@ static tsi_result ssl_handshaker_result_extract_peer(
result = peer_property_from_x509_subject(
verified_root_cert, &peer->properties[peer->property_count], true);
if (result != TSI_OK) {
gpr_log(GPR_DEBUG,
"Problem extracting subject from verified_root_cert. result: %d",
static_cast<int>(result));
VLOG(2) << "Problem extracting subject from verified_root_cert. result: "
<< result;
}
peer->property_count++;
}
@ -1676,7 +1674,7 @@ static tsi_result ssl_handshaker_process_bytes_from_peer(
bytes_written_into_ssl_size =
BIO_write(impl->network_io, bytes, static_cast<int>(*bytes_size));
if (bytes_written_into_ssl_size < 0) {
gpr_log(GPR_ERROR, "Could not write to memory BIO.");
LOG(ERROR) << "Could not write to memory BIO.";
if (error != nullptr) *error = "could not write to memory BIO";
impl->result = TSI_INTERNAL_ERROR;
return impl->result;
@ -1823,7 +1821,7 @@ static tsi_result ssl_handshaker_next(tsi_handshaker* self,
ssl_bytes_remaining(impl, &unused_bytes, &unused_bytes_size, error);
if (status != TSI_OK) return status;
if (unused_bytes_size > received_bytes_size) {
gpr_log(GPR_ERROR, "More unused bytes than received bytes.");
LOG(ERROR) << "More unused bytes than received bytes.";
gpr_free(unused_bytes);
if (error != nullptr) *error = "More unused bytes than received bytes.";
return TSI_INTERNAL_ERROR;
@ -1877,7 +1875,7 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
tsi_ssl_handshaker* impl = nullptr;
*handshaker = nullptr;
if (ctx == nullptr) {
gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
LOG(ERROR) << "SSL Context is null. Should never happen.";
return TSI_INTERNAL_ERROR;
}
if (ssl == nullptr) {
@ -1887,7 +1885,7 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
if (!BIO_new_bio_pair(&network_io, network_bio_buf_size, &ssl_io,
ssl_bio_buf_size)) {
gpr_log(GPR_ERROR, "BIO_new_bio_pair failed.");
LOG(ERROR) << "BIO_new_bio_pair failed.";
SSL_free(ssl);
return TSI_OUT_OF_RESOURCES;
}
@ -2076,7 +2074,7 @@ static int does_entry_match_name(absl::string_view entry,
// Wildchar subdomain matching.
if (entry.size() < 3 || entry[1] != '.') { // At least *.x
gpr_log(GPR_ERROR, "Invalid wildchar entry.");
LOG(ERROR) << "Invalid wildchar entry.";
return 0;
}
size_t name_subdomain_pos = name.find('.');
@ -2222,7 +2220,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
#endif
if (ssl_context == nullptr) {
grpc_core::LogSslErrorStack();
gpr_log(GPR_ERROR, "Could not create ssl context.");
LOG(ERROR) << "Could not create ssl context.";
return TSI_INVALID_ARGUMENT;
}
@ -2289,7 +2287,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
X509_VERIFY_PARAM_set_depth(param, kMaxChainLength);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Cannot load server root certificates.");
LOG(ERROR) << "Cannot load server root certificates.";
break;
}
}
@ -2308,7 +2306,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
if (SSL_CTX_set_alpn_protos(
ssl_context, impl->alpn_protocol_list,
static_cast<unsigned int>(impl->alpn_protocol_list_length))) {
gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
LOG(ERROR) << "Could not set alpn protocol list to context.";
result = TSI_INVALID_ARGUMENT;
break;
}
@ -2338,7 +2336,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
X509_STORE_set_verify_cb(cert_store, verify_cb);
if (!X509_STORE_load_locations(cert_store, nullptr,
options->crl_directory)) {
gpr_log(GPR_ERROR, "Failed to load CRL File from directory.");
LOG(ERROR) << "Failed to load CRL File from directory.";
} else {
X509_VERIFY_PARAM* param = X509_STORE_get0_param(cert_store);
X509_VERIFY_PARAM_set_flags(
@ -2443,7 +2441,7 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
#endif
if (impl->ssl_contexts[i] == nullptr) {
grpc_core::LogSslErrorStack();
gpr_log(GPR_ERROR, "Could not create ssl context.");
LOG(ERROR) << "Could not create ssl context.";
result = TSI_OUT_OF_RESOURCES;
break;
}
@ -2465,7 +2463,7 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
impl->ssl_contexts[i], kSslSessionIdContext,
GPR_ARRAY_SIZE(kSslSessionIdContext));
if (set_sid_ctx_result == 0) {
gpr_log(GPR_ERROR, "Failed to set session id context.");
LOG(ERROR) << "Failed to set session id context.";
result = TSI_INTERNAL_ERROR;
break;
}
@ -2475,7 +2473,7 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
impl->ssl_contexts[i],
const_cast<char*>(options->session_ticket_key),
options->session_ticket_key_size) == 0) {
gpr_log(GPR_ERROR, "Invalid STEK size.");
LOG(ERROR) << "Invalid STEK size.";
result = TSI_INVALID_ARGUMENT;
break;
}
@ -2488,7 +2486,7 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
strlen(options->pem_client_root_certs),
options->send_client_ca_list ? &root_names : nullptr);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Invalid verification certs.");
LOG(ERROR) << "Invalid verification certs.";
break;
}
if (options->send_client_ca_list) {
@ -2536,7 +2534,7 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
X509_STORE_set_verify_cb(cert_store, verify_cb);
if (!X509_STORE_load_locations(cert_store, nullptr,
options->crl_directory)) {
gpr_log(GPR_ERROR, "Failed to load CRL File from directory.");
LOG(ERROR) << "Failed to load CRL File from directory.";
} else {
X509_VERIFY_PARAM* param = X509_STORE_get0_param(cert_store);
X509_VERIFY_PARAM_set_flags(

@ -42,6 +42,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",

@ -115,6 +115,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/numeric:int128",
"absl/strings",
"absl/strings:str_format",
@ -157,6 +158,7 @@ grpc_cc_library(
"absl/container:flat_hash_map",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",

@ -736,6 +736,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/transport/call_spine.cc',
'src/core/lib/transport/connectivity_state.cc',
'src/core/lib/transport/error_utils.cc',
'src/core/lib/transport/interception_chain.cc',
'src/core/lib/transport/message.cc',
'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc',

@ -20,10 +20,12 @@
#include <stdlib.h>
#include <list>
#include <string>
#include <thread>
#include "absl/synchronization/notification.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/credentials.h>
@ -43,82 +45,126 @@ namespace grpc_core {
namespace channelz {
namespace testing {
// testing peer to access channel internals
class ChannelNodePeer {
// Testing peer to access channel internals.
class SubchannelNodePeer {
public:
explicit ChannelNodePeer(ChannelNode* node) : node_(node) {}
explicit SubchannelNodePeer(SubchannelNode* node) : node_(node) {}
ChannelTrace* trace() const { return &node_->trace_; }
private:
ChannelNode* node_;
SubchannelNode* node_;
};
size_t GetSizeofTraceEvent() { return sizeof(ChannelTrace::TraceEvent); }
namespace {
void ValidateJsonArraySize(const Json& array, size_t expected) {
if (expected == 0) {
ASSERT_EQ(array.type(), Json::Type::kNull);
} else {
ASSERT_EQ(array.type(), Json::Type::kArray);
EXPECT_EQ(array.array().size(), expected);
MATCHER_P(IsJsonString, expected, "is JSON string") {
if (!::testing::ExplainMatchResult(Json::Type::kString, arg.type(),
result_listener)) {
return false;
}
return ::testing::ExplainMatchResult(expected, arg.string(), result_listener);
}
void ValidateChannelTraceData(const Json& json,
size_t num_events_logged_expected,
size_t actual_num_events_expected) {
ASSERT_EQ(json.type(), Json::Type::kObject);
Json::Object object = json.object();
Json& num_events_logged_json = object["numEventsLogged"];
ASSERT_EQ(num_events_logged_json.type(), Json::Type::kString);
size_t num_events_logged = static_cast<size_t>(
strtol(num_events_logged_json.string().c_str(), nullptr, 0));
ASSERT_EQ(num_events_logged, num_events_logged_expected);
Json& start_time_json = object["creationTimestamp"];
ASSERT_EQ(start_time_json.type(), Json::Type::kString);
ValidateJsonArraySize(object["events"], actual_num_events_expected);
MATCHER_P(IsJsonStringNumber, expected, "is JSON string containing number") {
if (!::testing::ExplainMatchResult(Json::Type::kString, arg.type(),
result_listener)) {
return false;
}
int actual;
if (!absl::SimpleAtoi(arg.string(), &actual)) {
*result_listener << "JSON string \"" << arg.string()
<< " does not contain numeric value";
return false;
}
return ::testing::ExplainMatchResult(expected, actual, result_listener);
}
void AddSimpleTrace(ChannelTrace* tracer) {
tracer->AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("simple trace"));
MATCHER_P(IsJsonObject, matcher, "is JSON object") {
if (!::testing::ExplainMatchResult(Json::Type::kObject, arg.type(),
result_listener)) {
return false;
}
return ::testing::ExplainMatchResult(matcher, arg.object(), result_listener);
}
// checks for the existence of all the required members of the tracer.
void ValidateChannelTraceCustom(ChannelTrace* tracer, size_t num_events_logged,
size_t num_events_expected) {
Json json = tracer->RenderJson();
ASSERT_EQ(json.type(), Json::Type::kObject);
std::string json_str = JsonDump(json);
grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str.c_str());
ValidateChannelTraceData(json, num_events_logged, num_events_expected);
MATCHER_P(IsJsonArray, matcher, "is JSON array") {
if (!::testing::ExplainMatchResult(Json::Type::kArray, arg.type(),
result_listener)) {
return false;
}
return ::testing::ExplainMatchResult(matcher, arg.array(), result_listener);
}
void ValidateChannelTrace(ChannelTrace* tracer, size_t num_events_logged) {
ValidateChannelTraceCustom(tracer, num_events_logged, num_events_logged);
MATCHER_P2(IsTraceEvent, description, severity, "is trace event") {
return ::testing::ExplainMatchResult(
IsJsonObject(::testing::ElementsAre(
::testing::Pair("description", IsJsonString(description)),
::testing::Pair("severity", IsJsonString(severity)),
::testing::Pair("timestamp", IsJsonString(::testing::_)))),
arg, result_listener);
}
class ChannelFixture {
public:
explicit ChannelFixture(int max_tracer_event_memory) {
grpc_arg client_a = grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
max_tracer_event_memory);
grpc_channel_args client_args = {1, &client_a};
grpc_channel_credentials* creds = grpc_insecure_credentials_create();
channel_ = grpc_channel_create("fake_target", creds, &client_args);
grpc_channel_credentials_release(creds);
}
MATCHER_P3(IsTraceEventWithChannelRef, description, severity, channel_ref,
"is trace event with channel ref") {
return ::testing::ExplainMatchResult(
IsJsonObject(::testing::ElementsAre(
::testing::Pair("channelRef",
IsJsonObject(::testing::ElementsAre(::testing::Pair(
"channelId", IsJsonStringNumber(channel_ref))))),
::testing::Pair("description", IsJsonString(description)),
::testing::Pair("severity", IsJsonString(severity)),
::testing::Pair("timestamp", IsJsonString(::testing::_)))),
arg, result_listener);
}
~ChannelFixture() { grpc_channel_destroy(channel_); }
MATCHER_P3(IsTraceEventWithSubchannelRef, description, severity, subchannel_ref,
"is trace event with subchannel ref") {
return ::testing::ExplainMatchResult(
IsJsonObject(::testing::ElementsAre(
::testing::Pair("description", IsJsonString(description)),
::testing::Pair("severity", IsJsonString(severity)),
::testing::Pair(
"subchannelRef",
IsJsonObject(::testing::ElementsAre(::testing::Pair(
"subchannelId", IsJsonStringNumber(subchannel_ref))))),
::testing::Pair("timestamp", IsJsonString(::testing::_)))),
arg, result_listener);
}
grpc_channel* channel() { return channel_; }
MATCHER(IsEmptyChannelTrace, "is empty channel trace") {
return ::testing::ExplainMatchResult(
IsJsonObject(::testing::ElementsAre(
::testing::Pair("creationTimestamp", IsJsonString(::testing::_)))),
arg, result_listener);
}
private:
grpc_channel* channel_;
};
MATCHER_P2(IsChannelTrace, num_events_logged_expected, events_matcher,
"is channel trace") {
return ::testing::ExplainMatchResult(
IsJsonObject(::testing::ElementsAre(
::testing::Pair("creationTimestamp", IsJsonString(::testing::_)),
::testing::Pair("events", IsJsonArray(events_matcher)),
::testing::Pair("numEventsLogged",
IsJsonStringNumber(num_events_logged_expected)))),
arg, result_listener);
}
MATCHER_P(IsEmptyChannelTrace, num_events_logged_expected,
"is empty channel trace") {
return ::testing::ExplainMatchResult(
IsJsonObject(::testing::ElementsAre(
::testing::Pair("creationTimestamp", IsJsonString(::testing::_)),
::testing::Pair("numEventsLogged",
IsJsonStringNumber(num_events_logged_expected)))),
arg, result_listener);
}
void ValidateJsonProtoTranslation(const Json& json) {
std::string json_str = JsonDump(json);
grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str);
}
} // anonymous namespace
@ -129,21 +175,36 @@ const int kEventListMemoryLimit = 1024 * 1024;
TEST(ChannelTracerTest, BasicTest) {
ExecCtx exec_ctx;
ChannelTrace tracer(kEventListMemoryLimit);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("trace three"));
grpc_slice_from_static_string("one"));
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("two"));
tracer.AddTraceEvent(ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("three"));
tracer.AddTraceEvent(ChannelTrace::Severity::Error,
grpc_slice_from_static_string("trace four error"));
ValidateChannelTrace(&tracer, 4);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 6);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 10);
grpc_slice_from_static_string("four"));
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsChannelTrace(4, ::testing::ElementsAre(
IsTraceEvent("one", "CT_INFO"),
IsTraceEvent("two", "CT_INFO"),
IsTraceEvent("three", "CT_WARNING"),
IsTraceEvent("four", "CT_ERROR"))))
<< JsonDump(json);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("five"));
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("six"));
json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsChannelTrace(6, ::testing::ElementsAre(
IsTraceEvent("one", "CT_INFO"),
IsTraceEvent("two", "CT_INFO"),
IsTraceEvent("three", "CT_WARNING"),
IsTraceEvent("four", "CT_ERROR"),
IsTraceEvent("five", "CT_INFO"),
IsTraceEvent("six", "CT_INFO"))))
<< JsonDump(json);
}
// Tests more complex functionality, like a parent channel tracking
@ -152,119 +213,80 @@ TEST(ChannelTracerTest, BasicTest) {
TEST(ChannelTracerTest, ComplexTest) {
ExecCtx exec_ctx;
ChannelTrace tracer(kEventListMemoryLimit);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ChannelFixture channel1(kEventListMemoryLimit);
RefCountedPtr<ChannelNode> sc1 =
MakeRefCounted<ChannelNode>("fake_target", kEventListMemoryLimit, 0);
ChannelNodePeer sc1_peer(sc1.get());
tracer.AddTraceEventWithReference(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
ValidateChannelTrace(&tracer, 3);
AddSimpleTrace(sc1_peer.trace());
AddSimpleTrace(sc1_peer.trace());
AddSimpleTrace(sc1_peer.trace());
ValidateChannelTrace(sc1_peer.trace(), 3);
AddSimpleTrace(sc1_peer.trace());
AddSimpleTrace(sc1_peer.trace());
AddSimpleTrace(sc1_peer.trace());
ValidateChannelTrace(sc1_peer.trace(), 6);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 5);
ChannelFixture channel2(kEventListMemoryLimit);
RefCountedPtr<ChannelNode> sc2 =
MakeRefCounted<ChannelNode>("fake_target", kEventListMemoryLimit, 0);
tracer.AddTraceEventWithReference(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("LB channel two created"), sc2);
tracer.AddTraceEventWithReference(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
ValidateChannelTrace(&tracer, 7);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
sc1.reset();
sc2.reset();
}
// Test a case in which the parent channel has subchannels and the subchannels
// have connections. Ensures that everything lives as long as it should then
// gets deleted.
TEST(ChannelTracerTest, TestNesting) {
ExecCtx exec_ctx;
ChannelTrace tracer(kEventListMemoryLimit);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 2);
ChannelFixture channel1(kEventListMemoryLimit);
RefCountedPtr<ChannelNode> sc1 =
MakeRefCounted<ChannelNode>("fake_target", kEventListMemoryLimit, 0);
ChannelNodePeer sc1_peer(sc1.get());
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("one"));
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("two"));
auto subchannel_node = MakeRefCounted<SubchannelNode>("ipv4:1.2.3.4:5678",
kEventListMemoryLimit);
auto* subchannel_node_trace =
SubchannelNodePeer(subchannel_node.get()).trace();
tracer.AddTraceEventWithReference(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
ValidateChannelTrace(&tracer, 3);
AddSimpleTrace(sc1_peer.trace());
ChannelFixture channel2(kEventListMemoryLimit);
RefCountedPtr<ChannelNode> conn1 =
MakeRefCounted<ChannelNode>("fake_target", kEventListMemoryLimit, 0);
ChannelNodePeer conn1_peer(conn1.get());
// nesting one level deeper.
sc1_peer.trace()->AddTraceEventWithReference(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("connection one created"), conn1);
ValidateChannelTrace(&tracer, 3);
AddSimpleTrace(conn1_peer.trace());
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 5);
ValidateChannelTrace(conn1_peer.trace(), 1);
ChannelFixture channel3(kEventListMemoryLimit);
RefCountedPtr<ChannelNode> sc2 =
grpc_slice_from_static_string("subchannel one created"), subchannel_node);
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json,
IsChannelTrace(3, ::testing::ElementsAre(
IsTraceEvent("one", "CT_INFO"),
IsTraceEvent("two", "CT_INFO"),
IsTraceEventWithSubchannelRef(
"subchannel one created", "CT_INFO",
subchannel_node->uuid()))))
<< JsonDump(json);
subchannel_node_trace->AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("one"));
json = subchannel_node_trace->RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(
json,
IsChannelTrace(1, ::testing::ElementsAre(IsTraceEvent("one", "CT_INFO"))))
<< JsonDump(json);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("three"));
auto channel_node =
MakeRefCounted<ChannelNode>("fake_target", kEventListMemoryLimit, 0);
tracer.AddTraceEventWithReference(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel two created"), sc2);
// this trace should not get added to the parents children since it is already
// present in the tracer.
grpc_slice_from_static_string("LB channel two created"), channel_node);
tracer.AddTraceEventWithReference(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 8);
sc1.reset();
sc2.reset();
conn1.reset();
grpc_slice_from_static_string("subchannel one inactive"),
subchannel_node);
json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(
json,
IsChannelTrace(
6,
::testing::ElementsAre(
IsTraceEvent("one", "CT_INFO"), IsTraceEvent("two", "CT_INFO"),
IsTraceEventWithSubchannelRef("subchannel one created", "CT_INFO",
subchannel_node->uuid()),
IsTraceEvent("three", "CT_INFO"),
IsTraceEventWithChannelRef("LB channel two created", "CT_INFO",
channel_node->uuid()),
IsTraceEventWithSubchannelRef("subchannel one inactive",
"CT_WARNING",
subchannel_node->uuid()))))
<< JsonDump(json);
}
TEST(ChannelTracerTest, TestSmallMemoryLimit) {
ExecCtx exec_ctx;
// doesn't make sense, but serves a testing purpose for the channel tracing
// bookkeeping. All tracing events added should will get immediately garbage
// collected.
// Doesn't make sense in practice, but serves a testing purpose for the
// channel tracing bookkeeping. All tracing events added should get
// immediately garbage collected.
const int kSmallMemoryLimit = 1;
ChannelTrace tracer(kSmallMemoryLimit);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("trace three"));
tracer.AddTraceEvent(ChannelTrace::Severity::Error,
grpc_slice_from_static_string("trace four error"));
ValidateChannelTraceCustom(&tracer, 4, 0);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTraceCustom(&tracer, 6, 0);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTraceCustom(&tracer, 10, 0);
const size_t kNumEvents = 4;
for (size_t i = 0; i < kNumEvents; ++i) {
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("trace"));
}
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsEmptyChannelTrace(kNumEvents)) << JsonDump(json);
}
TEST(ChannelTracerTest, TestEviction) {
@ -272,15 +294,28 @@ TEST(ChannelTracerTest, TestEviction) {
const int kTraceEventSize = GetSizeofTraceEvent();
const int kNumEvents = 5;
ChannelTrace tracer(kTraceEventSize * kNumEvents);
std::list<::testing::Matcher<Json>> matchers;
for (int i = 1; i <= kNumEvents; ++i) {
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, i);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("trace"));
matchers.push_back(IsTraceEvent("trace", "CT_INFO"));
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsChannelTrace(i, ::testing::ElementsAreArray(matchers)))
<< JsonDump(json);
}
// at this point the list is full, and each subsequent enntry will cause an
// At this point the list is full, and each subsequent enntry will cause an
// eviction.
for (int i = 1; i <= kNumEvents; ++i) {
AddSimpleTrace(&tracer);
ValidateChannelTraceCustom(&tracer, kNumEvents + i, kNumEvents);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("new"));
matchers.pop_front();
matchers.push_back(IsTraceEvent("new", "CT_INFO"));
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsChannelTrace(kNumEvents + i,
::testing::ElementsAreArray(matchers)))
<< JsonDump(json);
}
}
@ -289,18 +324,32 @@ TEST(ChannelTracerTest, TestMultipleEviction) {
const int kTraceEventSize = GetSizeofTraceEvent();
const int kNumEvents = 5;
ChannelTrace tracer(kTraceEventSize * kNumEvents);
std::list<::testing::Matcher<Json>> matchers;
for (int i = 1; i <= kNumEvents; ++i) {
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, i);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("trace"));
matchers.push_back(IsTraceEvent("trace", "CT_INFO"));
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsChannelTrace(i, ::testing::ElementsAreArray(matchers)))
<< JsonDump(json);
}
// at this point the list is full, and each subsequent enntry will cause an
// At this point the list is full, and each subsequent enntry will cause an
// eviction. We will now add in a trace event that has a copied string. This
// uses more memory, so it will cause a double eviciction
// uses more memory, so it will cause a double eviciction.
tracer.AddTraceEvent(
ChannelTrace::Severity::Info,
grpc_slice_from_copied_string(
"long enough string to trigger a multiple eviction"));
ValidateChannelTraceCustom(&tracer, kNumEvents + 1, kNumEvents - 1);
matchers.pop_front();
matchers.pop_front();
matchers.push_back(IsTraceEvent(
"long enough string to trigger a multiple eviction", "CT_INFO"));
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsChannelTrace(kNumEvents + 1,
::testing::ElementsAreArray(matchers)))
<< JsonDump(json);
}
TEST(ChannelTracerTest, TestTotalEviction) {
@ -308,15 +357,23 @@ TEST(ChannelTracerTest, TestTotalEviction) {
const int kTraceEventSize = GetSizeofTraceEvent();
const int kNumEvents = 5;
ChannelTrace tracer(kTraceEventSize * kNumEvents);
std::list<::testing::Matcher<Json>> matchers;
for (int i = 1; i <= kNumEvents; ++i) {
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, i);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("trace"));
matchers.push_back(IsTraceEvent("trace", "CT_INFO"));
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsChannelTrace(i, ::testing::ElementsAreArray(matchers)))
<< JsonDump(json);
}
// at this point the list is full. Now we add such a big slice that
// At this point the list is full. Now we add such a big slice that
// everything gets evicted.
grpc_slice huge_slice = grpc_slice_malloc(kTraceEventSize * (kNumEvents + 1));
tracer.AddTraceEvent(ChannelTrace::Severity::Info, huge_slice);
ValidateChannelTraceCustom(&tracer, kNumEvents + 1, 0);
Json json = tracer.RenderJson();
ValidateJsonProtoTranslation(json);
EXPECT_THAT(json, IsEmptyChannelTrace(kNumEvents + 1)) << JsonDump(json);
}
// Tests that the code is thread-safe.
@ -328,7 +385,8 @@ TEST(ChannelTracerTest, ThreadSafety) {
for (size_t i = 0; i < 10; ++i) {
threads.push_back(std::make_unique<std::thread>([&]() {
do {
AddSimpleTrace(&tracer);
tracer.AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("trace"));
} while (!done.HasBeenNotified());
}));
}

@ -103,9 +103,6 @@ CORE_END2END_TEST(CoreEnd2endTest, FilterContext) {
CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) {
for (auto type : {GRPC_CLIENT_CHANNEL, GRPC_CLIENT_SUBCHANNEL,
GRPC_CLIENT_DIRECT_CHANNEL, GRPC_SERVER_CHANNEL}) {
if (type == GRPC_SERVER_CHANNEL && IsPromiseBasedServerCallEnabled()) {
continue;
}
builder->channel_init()->RegisterFilter(type, &test_filter);
}
});

@ -23,7 +23,10 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channel_stack_builder_impl.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_arena_allocator.h"
#include "test/core/test_util/test_config.h"
namespace grpc_core {
@ -208,7 +211,7 @@ class TestFilter1 {
explicit TestFilter1(int* p) : p_(p) {}
static absl::StatusOr<std::unique_ptr<TestFilter1>> Create(
const ChannelArgs& args, Empty) {
const ChannelArgs& args, ChannelFilter::Args) {
EXPECT_EQ(args.GetInt("foo"), 1);
return std::make_unique<TestFilter1>(args.GetPointer<int>("p"));
}
@ -250,19 +253,23 @@ TEST(ChannelInitTest, CanCreateFilterWithCall) {
b.RegisterFilter<TestFilter1>(GRPC_CLIENT_CHANNEL);
auto init = b.Build();
int p = 0;
auto segment = init.CreateStackSegment(
GRPC_CLIENT_CHANNEL,
ChannelArgs().Set("foo", 1).Set("p", ChannelArgs::UnownedPointer(&p)));
ASSERT_TRUE(segment.ok()) << segment.status();
CallFilters::StackBuilder stack_builder;
segment->AddToCallFilterStack(stack_builder);
segment = absl::CancelledError(); // force the segment to be destroyed
auto stack = stack_builder.Build();
{
CallFilters call_filters(Arena::MakePooled<ClientMetadata>());
call_filters.SetStack(std::move(stack));
}
InterceptionChainBuilder chain_builder{
ChannelArgs().Set("foo", 1).Set("p", ChannelArgs::UnownedPointer(&p))};
init.AddToInterceptionChainBuilder(GRPC_CLIENT_CHANNEL, chain_builder);
int handled = 0;
auto stack = chain_builder.Build(MakeCallDestinationFromHandlerFunction(
[&handled](CallHandler) { ++handled; }));
ASSERT_TRUE(stack.ok()) << stack.status();
RefCountedPtr<CallArenaAllocator> allocator =
MakeRefCounted<CallArenaAllocator>(
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
"test"),
1024);
auto call = MakeCallPair(Arena::MakePooled<ClientMetadata>(), nullptr,
allocator->MakeArena(), allocator, nullptr);
(*stack)->StartCall(std::move(call.handler));
EXPECT_EQ(p, 1);
EXPECT_EQ(handled, 1);
}
} // namespace

@ -39,6 +39,7 @@
#include "src/core/lib/uri/uri_parser.h"
#include "src/core/server/server.h"
#include "test/core/event_engine/event_engine_test_utils.h"
#include "test/core/test_util/build.h"
#include "test/core/test_util/port.h"
#include "test/core/test_util/test_config.h"
@ -67,7 +68,10 @@ class ChaoticGoodServerTest : public ::testing::Test {
auto ev = grpc_completion_queue_pluck(
shutdown_cq, nullptr, grpc_timeout_milliseconds_to_deadline(15000),
nullptr);
CHECK(ev.type == GRPC_OP_COMPLETE);
if (ev.type == GRPC_QUEUE_TIMEOUT) {
AsanAssertNoLeaks();
}
CHECK_EQ(ev.type, GRPC_OP_COMPLETE);
CHECK_EQ(ev.tag, nullptr);
grpc_completion_queue_destroy(shutdown_cq);
grpc_server_destroy(server_);

@ -82,19 +82,19 @@ ServerMetadataHandle TestTrailingMetadata() {
return md;
}
class MockAcceptor : public ServerTransport::Acceptor {
class MockCallDestination : public UnstartedCallDestination {
public:
virtual ~MockAcceptor() = default;
MOCK_METHOD(Arena*, CreateArena, (), (override));
MOCK_METHOD(absl::StatusOr<CallInitiator>, CreateCall,
(ClientMetadataHandle client_initial_metadata, Arena* arena),
~MockCallDestination() override = default;
MOCK_METHOD(void, Orphaned, (), (override));
MOCK_METHOD(void, StartCall, (UnstartedCallHandler unstarted_call_handler),
(override));
};
TEST_F(TransportTest, ReadAndWriteOneMessage) {
MockPromiseEndpoint control_endpoint;
MockPromiseEndpoint data_endpoint;
StrictMock<MockAcceptor> acceptor;
auto call_destination = MakeRefCounted<StrictMock<MockCallDestination>>();
EXPECT_CALL(*call_destination, Orphaned()).Times(1);
auto transport = MakeOrphanable<ChaoticGoodServerTransport>(
CoreConfiguration::Get()
.channel_args_preconditioning()
@ -112,19 +112,21 @@ TEST_F(TransportTest, ReadAndWriteOneMessage) {
data_endpoint.ExpectRead(
{EventEngineSlice::FromCopiedString("12345678"), Zeros(56)}, nullptr);
// Once that's read we'll create a new call
auto* call_arena = MakeArena();
EXPECT_CALL(acceptor, CreateArena).WillOnce(Return(call_arena));
StrictMock<MockFunction<void()>> on_done;
EXPECT_CALL(acceptor, CreateCall(_, call_arena))
.WillOnce(WithArgs<0>([this, call_arena, &on_done](
ClientMetadataHandle client_initial_metadata) {
EXPECT_EQ(client_initial_metadata->get_pointer(HttpPathMetadata())
auto control_address =
grpc_event_engine::experimental::URIToResolvedAddress("ipv4:1.2.3.4:5678")
.value();
EXPECT_CALL(*control_endpoint.endpoint, GetPeerAddress)
.WillRepeatedly([&control_address]() { return control_address; });
EXPECT_CALL(*call_destination, StartCall(_))
.WillOnce(WithArgs<0>([&on_done](
UnstartedCallHandler unstarted_call_handler) {
EXPECT_EQ(unstarted_call_handler.UnprocessedClientInitialMetadata()
.get_pointer(HttpPathMetadata())
->as_string_view(),
"/demo.Service/Step");
CallInitiatorAndHandler call = MakeCallPair(
std::move(client_initial_metadata), event_engine().get(),
call_arena, call_arena_allocator(), nullptr);
auto handler = call.handler.V2HackToStartCallWithoutACallFilterStack();
auto handler =
unstarted_call_handler.V2HackToStartCallWithoutACallFilterStack();
handler.SpawnInfallible("test-io", [&on_done, handler]() mutable {
return Seq(
handler.PullClientInitialMetadata(),
@ -163,9 +165,8 @@ TEST_F(TransportTest, ReadAndWriteOneMessage) {
return Empty{};
});
});
return std::move(call.initiator);
}));
transport->SetAcceptor(&acceptor);
transport->SetCallDestination(call_destination);
EXPECT_CALL(on_done, Call());
EXPECT_CALL(*control_endpoint.endpoint, Read)
.InSequence(control_endpoint.read_sequence)

@ -62,7 +62,7 @@ void FillMetadata(const std::vector<std::pair<std::string, std::string>>& md,
} // namespace
TRANSPORT_TEST(UnaryWithSomeContent) {
SetServerAcceptor();
SetServerCallDestination();
const auto client_initial_metadata = RandomMetadata();
const auto server_initial_metadata = RandomMetadata();
const auto server_trailing_metadata = RandomMetadata();

@ -17,7 +17,7 @@
namespace grpc_core {
TRANSPORT_TEST(MetadataOnlyRequest) {
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -72,7 +72,7 @@ TRANSPORT_TEST(MetadataOnlyRequestServerAbortsAfterInitialMetadata) {
"wrong status code: we don't care for any cases we're "
"rolling out soon, so leaving this disabled.";
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -125,7 +125,7 @@ TRANSPORT_TEST(MetadataOnlyRequestServerAbortsImmediately) {
"wrong status code: we don't care for any cases we're "
"rolling out soon, so leaving this disabled.";
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -165,7 +165,7 @@ TRANSPORT_TEST(MetadataOnlyRequestServerAbortsImmediately) {
}
TRANSPORT_TEST(CanCreateCallThenAbandonIt) {
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -178,7 +178,7 @@ TRANSPORT_TEST(CanCreateCallThenAbandonIt) {
}
TRANSPORT_TEST(UnaryRequest) {
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -257,7 +257,7 @@ TRANSPORT_TEST(UnaryRequest) {
}
TRANSPORT_TEST(UnaryRequestOmitCheckEndOfStream) {
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -326,7 +326,7 @@ TRANSPORT_TEST(UnaryRequestOmitCheckEndOfStream) {
}
TRANSPORT_TEST(UnaryRequestWaitForServerInitialMetadataBeforeSendingPayload) {
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -404,7 +404,7 @@ TRANSPORT_TEST(UnaryRequestWaitForServerInitialMetadataBeforeSendingPayload) {
}
TRANSPORT_TEST(ClientStreamingRequest) {
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));
@ -518,7 +518,7 @@ TRANSPORT_TEST(ClientStreamingRequest) {
}
TRANSPORT_TEST(ServerStreamingRequest) {
SetServerAcceptor();
SetServerCallDestination();
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), Slice::FromExternalString("/foo/bar"));
auto initiator = CreateCall(std::move(md));

@ -13,12 +13,16 @@
// limitations under the License.
#include "src/core/ext/transport/inproc/inproc_transport.h"
#include "src/core/lib/config/core_configuration.h"
#include "test/core/transport/test_suite/fixture.h"
namespace grpc_core {
TRANSPORT_FIXTURE(Inproc) {
auto transports = MakeInProcessTransportPair();
auto transports =
MakeInProcessTransportPair(CoreConfiguration::Get()
.channel_args_preconditioning()
.PreconditionChannelArgs(nullptr));
return {std::move(transports.first), std::move(transports.second)};
}

@ -20,8 +20,8 @@ TRANSPORT_TEST(NoOp) {}
TRANSPORT_TEST(WaitForAllPendingWork) { WaitForAllPendingWork(); }
TRANSPORT_TEST(SetServerAcceptorAndFinish) {
SetServerAcceptor();
TRANSPORT_TEST(SetServerCallDestinationAndFinish) {
SetServerCallDestination();
WaitForAllPendingWork();
}

@ -19,7 +19,7 @@
namespace grpc_core {
TRANSPORT_TEST(ManyUnaryRequests) {
SetServerAcceptor();
SetServerCallDestination();
const int kNumRequests = absl::LogUniform<int>(rng(), 10, 100);
std::list<std::string> call_names;
auto make_call_name = [&call_names](int i,

@ -52,8 +52,9 @@ void TransportTest::RunTest() {
event_engine_->UnsetGlobalHooks();
}
void TransportTest::SetServerAcceptor() {
transport_pair_.server->server_transport()->SetAcceptor(&acceptor_);
void TransportTest::SetServerCallDestination() {
transport_pair_.server->server_transport()->SetCallDestination(
server_call_destination_);
}
CallInitiator TransportTest::CreateCall(
@ -71,8 +72,10 @@ CallInitiator TransportTest::CreateCall(
CallHandler TransportTest::TickUntilServerCall() {
WatchDog watchdog(this);
for (;;) {
auto handler = acceptor_.PopHandler();
if (handler.has_value()) return std::move(*handler);
auto handler = server_call_destination_->PopHandler();
if (handler.has_value()) {
return std::move(*handler);
}
event_engine_->Tick();
}
}
@ -227,22 +230,14 @@ std::string TransportTest::RandomMessage() {
}
///////////////////////////////////////////////////////////////////////////////
// TransportTest::Acceptor
Arena* TransportTest::Acceptor::CreateArena() {
return test_->call_arena_allocator_->MakeArena();
}
// TransportTest::ServerCallDestination
absl::StatusOr<CallInitiator> TransportTest::Acceptor::CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) {
auto call = MakeCallPair(std::move(client_initial_metadata),
test_->event_engine_.get(), arena,
test_->call_arena_allocator_, nullptr);
handlers_.push(call.handler.V2HackToStartCallWithoutACallFilterStack());
return std::move(call.initiator);
void TransportTest::ServerCallDestination::StartCall(
UnstartedCallHandler handler) {
handlers_.push(handler.V2HackToStartCallWithoutACallFilterStack());
}
absl::optional<CallHandler> TransportTest::Acceptor::PopHandler() {
absl::optional<CallHandler> TransportTest::ServerCallDestination::PopHandler() {
if (!handlers_.empty()) {
auto handler = std::move(handlers_.front());
handlers_.pop();

@ -32,6 +32,7 @@
#include "src/core/lib/resource_quota/resource_quota.h"
#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h"
#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h"
#include "test/core/test_util/test_config.h"
#include "test/core/transport/test_suite/fixture.h"
namespace grpc_core {
@ -220,7 +221,7 @@ class TransportTest : public ::testing::Test {
fixture_(std::move(fixture)),
rng_(rng) {}
void SetServerAcceptor();
void SetServerCallDestination();
CallInitiator CreateCall(ClientMetadataHandle client_initial_metadata);
std::string RandomString(int min_length, int max_length,
@ -270,18 +271,14 @@ class TransportTest : public ::testing::Test {
void Timeout();
class Acceptor final : public ServerTransport::Acceptor {
class ServerCallDestination final : public UnstartedCallDestination {
public:
explicit Acceptor(TransportTest* test) : test_(test) {}
Arena* CreateArena() override;
absl::StatusOr<CallInitiator> CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) override;
void StartCall(UnstartedCallHandler unstarted_call_handler) override;
void Orphaned() override {}
absl::optional<CallHandler> PopHandler();
private:
std::queue<CallHandler> handlers_;
TransportTest* const test_;
};
class WatchDog {
@ -296,6 +293,7 @@ class TransportTest : public ::testing::Test {
[this]() { test_->Timeout(); })};
};
grpc::testing::TestGrpcScope grpc_scope_;
std::shared_ptr<grpc_event_engine::experimental::FuzzingEventEngine>
event_engine_{
std::make_shared<grpc_event_engine::experimental::FuzzingEventEngine>(
@ -313,7 +311,8 @@ class TransportTest : public ::testing::Test {
->memory_quota()
->CreateMemoryAllocator("test-allocator"),
1024)};
Acceptor acceptor_{this};
RefCountedPtr<ServerCallDestination> server_call_destination_ =
MakeRefCounted<ServerCallDestination>();
TransportFixture::ClientAndServerTransportPair transport_pair_ =
fixture_->CreateTransportPair(event_engine_);
std::queue<std::shared_ptr<transport_test_detail::ActionState>>

@ -115,6 +115,7 @@ grpc_cc_test(
"gtest",
],
language = "C++",
shard_count = 5,
tags = ["no_windows"],
deps = [
":transport_security_test_lib",

@ -111,7 +111,6 @@ int main(int argc, char** argv) {
grpc_core::ForceEnableExperiment("event_engine_client", true);
grpc_core::ForceEnableExperiment("event_engine_listener", true);
grpc_core::ForceEnableExperiment("promise_based_client_call", true);
grpc_core::ForceEnableExperiment("promise_based_server_call", true);
grpc_core::ForceEnableExperiment("chaotic_good", true);
grpc::testing::TestEnvironment env(&argc, argv);
LibraryInitializer libInit;

@ -41,7 +41,7 @@ namespace {
// then back to json. This ensures that the json string was correctly formatted
// according to https://developers.google.com/protocol-buffers/docs/proto3#json
template <typename Message>
void VaidateProtoJsonTranslation(const std::string& json_str) {
void VaidateProtoJsonTranslation(absl::string_view json_str) {
Message msg;
grpc::protobuf::json::JsonParseOptions parse_options;
// If the following line is failing, then uncomment the last line of the
@ -73,41 +73,44 @@ void VaidateProtoJsonTranslation(const std::string& json_str) {
namespace testing {
void ValidateChannelTraceProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::ChannelTrace>(json_c_str);
void ValidateChannelTraceProtoJsonTranslation(absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::ChannelTrace>(json_string);
}
void ValidateChannelProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Channel>(json_c_str);
void ValidateChannelProtoJsonTranslation(absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Channel>(json_string);
}
void ValidateGetTopChannelsResponseProtoJsonTranslation(
const char* json_c_str) {
absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetTopChannelsResponse>(
json_c_str);
json_string);
}
void ValidateGetChannelResponseProtoJsonTranslation(const char* json_c_str) {
void ValidateGetChannelResponseProtoJsonTranslation(
absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetChannelResponse>(
json_c_str);
json_string);
}
void ValidateGetServerResponseProtoJsonTranslation(const char* json_c_str) {
void ValidateGetServerResponseProtoJsonTranslation(
absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetServerResponse>(
json_c_str);
json_string);
}
void ValidateSubchannelProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Subchannel>(json_c_str);
void ValidateSubchannelProtoJsonTranslation(absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Subchannel>(json_string);
}
void ValidateServerProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Server>(json_c_str);
void ValidateServerProtoJsonTranslation(absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Server>(json_string);
}
void ValidateGetServersResponseProtoJsonTranslation(const char* json_c_str) {
void ValidateGetServersResponseProtoJsonTranslation(
absl::string_view json_string) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetServersResponse>(
json_c_str);
json_string);
}
} // namespace testing

@ -19,17 +19,23 @@
#ifndef GRPC_TEST_CPP_UTIL_CHANNEL_TRACE_PROTO_HELPER_H
#define GRPC_TEST_CPP_UTIL_CHANNEL_TRACE_PROTO_HELPER_H
#include "absl/strings/string_view.h"
namespace grpc {
namespace testing {
void ValidateChannelTraceProtoJsonTranslation(const char* json_c_str);
void ValidateChannelProtoJsonTranslation(const char* json_c_str);
void ValidateGetTopChannelsResponseProtoJsonTranslation(const char* json_c_str);
void ValidateGetChannelResponseProtoJsonTranslation(const char* json_c_str);
void ValidateGetServerResponseProtoJsonTranslation(const char* json_c_str);
void ValidateSubchannelProtoJsonTranslation(const char* json_c_str);
void ValidateServerProtoJsonTranslation(const char* json_c_str);
void ValidateGetServersResponseProtoJsonTranslation(const char* json_c_str);
void ValidateChannelTraceProtoJsonTranslation(absl::string_view json_string);
void ValidateChannelProtoJsonTranslation(absl::string_view json_string);
void ValidateGetTopChannelsResponseProtoJsonTranslation(
absl::string_view json_string);
void ValidateGetChannelResponseProtoJsonTranslation(
absl::string_view json_string);
void ValidateGetServerResponseProtoJsonTranslation(
absl::string_view json_string);
void ValidateSubchannelProtoJsonTranslation(absl::string_view json_string);
void ValidateServerProtoJsonTranslation(absl::string_view json_string);
void ValidateGetServersResponseProtoJsonTranslation(
absl::string_view json_string);
} // namespace testing
} // namespace grpc

@ -2750,6 +2750,7 @@ src/core/lib/transport/bdp_estimator.cc \
src/core/lib/transport/bdp_estimator.h \
src/core/lib/transport/call_arena_allocator.cc \
src/core/lib/transport/call_arena_allocator.h \
src/core/lib/transport/call_destination.h \
src/core/lib/transport/call_filters.cc \
src/core/lib/transport/call_filters.h \
src/core/lib/transport/call_final_info.cc \
@ -2762,6 +2763,8 @@ src/core/lib/transport/custom_metadata.h \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/error_utils.h \
src/core/lib/transport/http2_errors.h \
src/core/lib/transport/interception_chain.cc \
src/core/lib/transport/interception_chain.h \
src/core/lib/transport/message.cc \
src/core/lib/transport/message.h \
src/core/lib/transport/metadata.cc \

@ -2527,6 +2527,7 @@ src/core/lib/transport/bdp_estimator.cc \
src/core/lib/transport/bdp_estimator.h \
src/core/lib/transport/call_arena_allocator.cc \
src/core/lib/transport/call_arena_allocator.h \
src/core/lib/transport/call_destination.h \
src/core/lib/transport/call_filters.cc \
src/core/lib/transport/call_filters.h \
src/core/lib/transport/call_final_info.cc \
@ -2539,6 +2540,8 @@ src/core/lib/transport/custom_metadata.h \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/error_utils.h \
src/core/lib/transport/http2_errors.h \
src/core/lib/transport/interception_chain.cc \
src/core/lib/transport/interception_chain.h \
src/core/lib/transport/message.cc \
src/core/lib/transport/message.h \
src/core/lib/transport/metadata.cc \

Loading…
Cancel
Save