Merge branch 'master' of github.com:grpc/grpc into tls_version

pull/34861/head
Luwei Ge 12 months ago
commit f9a1215ac1
  1. 2
      .bazelversion
  2. 6
      .gitattributes
  3. 6
      .github/labeler.yml
  4. 3
      .github/workflows/pr-auto-fix.yaml
  5. 15
      .github/workflows/pr-auto-tag.yaml
  6. 2
      .gitignore
  7. 26
      BUILD
  8. 1569
      CMakeLists.txt
  9. 1469
      Makefile
  10. 3
      OWNERS
  11. 1520
      Package.swift
  12. 6
      WORKSPACE
  13. 2
      _metadata.py
  14. 74
      bazel/experiments.bzl
  15. 2
      bazel/googleapis.BUILD
  16. 13
      bazel/grpc_build_system.bzl
  17. 61
      bazel/grpc_deps.bzl
  18. 3
      bazel/grpc_extra_deps.bzl
  19. 3
      bazel/supported_versions.txt
  20. 7
      bazel/test_experiments.bzl
  21. 14
      bazel/update_mirror.sh
  22. 3272
      build_autogenerated.yaml
  23. 2
      build_config.rb
  24. 12
      build_handwritten.yaml
  25. 2
      cmake/upb.cmake
  26. 848
      config.m4
  27. 1118
      config.w32
  28. 11
      doc/bazel_support.md
  29. 3
      doc/g_stands_for.md
  30. 12
      doc/service_config.md
  31. 42
      examples/cpp/debugging/BUILD
  32. 132
      examples/cpp/debugging/README.md
  33. 92
      examples/cpp/debugging/crashing_greeter_client.cc
  34. 86
      examples/cpp/debugging/greeter_callback_server_admin.cc
  35. 22
      fuzztest/core/transport/chttp2/BUILD
  36. 79
      fuzztest/core/transport/chttp2/hpack_encoder_timeout_test.cc
  37. 1750
      gRPC-C++.podspec
  38. 2390
      gRPC-Core.podspec
  39. 2
      gRPC-ProtoRPC.podspec
  40. 2
      gRPC-RxLibrary.podspec
  41. 4
      gRPC.podspec
  42. 1514
      grpc.gemspec
  43. 807
      grpc.gyp
  44. 71
      include/grpc/event_engine/event_engine.h
  45. 6
      include/grpc/event_engine/internal/memory_allocator_impl.h
  46. 4
      include/grpc/event_engine/memory_allocator.h
  47. 13
      include/grpc/grpc_crl_provider.h
  48. 5
      include/grpc/grpc_security.h
  49. 7
      include/grpc/impl/channel_arg_names.h
  50. 2
      include/grpc/impl/slice_type.h
  51. 5
      include/grpcpp/security/tls_credentials_options.h
  52. 4
      include/grpcpp/version_info.h
  53. 1518
      package.xml
  54. 1
      requirements.bazel.txt
  55. 2
      setup.cfg
  56. 6
      setup.py
  57. 297
      src/core/BUILD
  58. 18
      src/core/ext/filters/client_channel/client_channel.cc
  59. 75
      src/core/ext/filters/client_channel/lb_policy/address_filtering.cc
  60. 5
      src/core/ext/filters/client_channel/lb_policy/address_filtering.h
  61. 2
      src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
  62. 17
      src/core/ext/filters/client_channel/lb_policy/endpoint_list.cc
  63. 8
      src/core/ext/filters/client_channel/lb_policy/endpoint_list.h
  64. 212
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  65. 5
      src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc
  66. 182
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  67. 3
      src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
  68. 18
      src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc
  69. 27
      src/core/ext/filters/client_channel/lb_policy/rls/rls.cc
  70. 29
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  71. 20
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  72. 44
      src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc
  73. 15
      src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
  74. 43
      src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
  75. 4
      src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc
  76. 5
      src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc
  77. 109
      src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc
  78. 85
      src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc
  79. 9
      src/core/ext/filters/client_channel/lb_policy/xds/xds_wrr_locality.cc
  80. 263
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
  81. 71
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
  82. 1
      src/core/ext/filters/client_channel/retry_filter.cc
  83. 12
      src/core/ext/filters/deadline/deadline_filter.cc
  84. 55
      src/core/ext/filters/http/client/http_client_filter.cc
  85. 15
      src/core/ext/filters/http/client/http_client_filter.h
  86. 82
      src/core/ext/filters/http/server/http_server_filter.cc
  87. 15
      src/core/ext/filters/http/server/http_server_filter.h
  88. 124
      src/core/ext/filters/message_size/message_size_filter.cc
  89. 58
      src/core/ext/filters/message_size/message_size_filter.h
  90. 116
      src/core/ext/transport/chaotic_good/client_transport.cc
  91. 140
      src/core/ext/transport/chaotic_good/client_transport.h
  92. 6
      src/core/ext/transport/chaotic_good/frame.cc
  93. 1
      src/core/ext/transport/chaotic_good/frame.h
  94. 136
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  95. 9
      src/core/ext/transport/chttp2/transport/chttp2_transport.h
  96. 20
      src/core/ext/transport/chttp2/transport/flow_control.cc
  97. 2
      src/core/ext/transport/chttp2/transport/frame_rst_stream.cc
  98. 26
      src/core/ext/transport/chttp2/transport/hpack_encoder.cc
  99. 10
      src/core/ext/transport/chttp2/transport/hpack_encoder.h
  100. 7
      src/core/ext/transport/chttp2/transport/hpack_encoder_table.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1 +1 @@
6.3.2 6.4.0

6
.gitattributes vendored

@ -1,5 +1,5 @@
src/core/ext/upb-generated/** linguist-generated=true src/core/ext/upb-gen/** linguist-generated=true
src/core/ext/upbdefs-generated/** linguist-generated=true src/core/ext/upbdefs-gen/** linguist-generated=true
Makefile linguist-generated=true Makefile linguist-generated=true
BUILD.gn linguist-generated=true BUILD.gn linguist-generated=true
CMakeLists.txt linguist-generated=true CMakeLists.txt linguist-generated=true
@ -36,4 +36,4 @@ src/core/lib/debug/stats_data.cc linguist-generated=true
src/core/lib/experiments/experiments.h linguist-generated=true src/core/lib/experiments/experiments.h linguist-generated=true
src/core/lib/experiments/experiments.cc linguist-generated=true src/core/lib/experiments/experiments.cc linguist-generated=true
bazel/experiments.bzl linguist-generated=true bazel/experiments.bzl linguist-generated=true
test/cpp/microbenchmarks/huffman_geometries/** linguist-generated=true test/cpp/microbenchmarks/huffman_geometries/** linguist-generated=true

@ -52,9 +52,3 @@ lang/ruby:
"lang/C#": "lang/C#":
- src/compiler/csharp* - src/compiler/csharp*
- src/csharp/** - src/csharp/**
"disposition/Needs Internal Changes":
- src/core/lib/event_engine/windows/**
- src/core/lib/gpr/windows/**
- src/core/lib/gprpp/windows/**
- test/core/event_engine/windows/**

@ -48,8 +48,9 @@ jobs:
with: with:
script: | script: |
// If you'd like not to run this code on your commits, add your github user id here: // If you'd like not to run this code on your commits, add your github user id here:
NO_AUTOFIX_USERS = [] NO_AUTOFIX_USERS = ["copybara-service[bot]"]
const { owner, repo } = context.repo const { owner, repo } = context.repo
console.log("Actor: " + context.actor);
if (NO_AUTOFIX_USERS.includes(context.actor)) { if (NO_AUTOFIX_USERS.includes(context.actor)) {
console.log('Cancelling'); console.log('Cancelling');
const run_id = "${{ github.run_id }}"; const run_id = "${{ github.run_id }}";

@ -1,4 +1,4 @@
name: PR Title Check & Tag name: PR Auto Tag
on: on:
pull_request_target: pull_request_target:
types: [opened, reopened, synchronize, edited] types: [opened, reopened, synchronize, edited]
@ -17,16 +17,3 @@ jobs:
with: with:
repo-token: "${{ secrets.GITHUB_TOKEN }}" repo-token: "${{ secrets.GITHUB_TOKEN }}"
sync-labels: "" sync-labels: ""
title-check:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: thehanimo/pr-title-checker@v1.3.5
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
pass_on_octokit_error: false
configuration_path: ".github/pr_title_checker_config.json"

2
.gitignore vendored

@ -17,7 +17,7 @@ cython_debug/
dist/ dist/
htmlcov/ htmlcov/
py3*/ py3*/
python_build/ pyb/
python_pylint_venv/ python_pylint_venv/
src/python/grpcio_*/=* src/python/grpcio_*/=*
src/python/grpcio_*/build/ src/python/grpcio_*/build/

26
BUILD

@ -30,8 +30,8 @@ licenses(["reciprocal"])
package( package(
default_visibility = ["//visibility:public"], default_visibility = ["//visibility:public"],
features = [ features = [
"layering_check",
"-parse_headers", "-parse_headers",
"layering_check",
], ],
) )
@ -211,11 +211,11 @@ config_setting(
python_config_settings() python_config_settings()
# This should be updated along with build_handwritten.yaml # This should be updated along with build_handwritten.yaml
g_stands_for = "gjallarhorn" # @unused g_stands_for = "grand" # @unused
core_version = "36.0.0" # @unused core_version = "37.0.0" # @unused
version = "1.60.0-dev" # @unused version = "1.61.0-dev" # @unused
GPR_PUBLIC_HDRS = [ GPR_PUBLIC_HDRS = [
"include/grpc/support/alloc.h", "include/grpc/support/alloc.h",
@ -1009,6 +1009,7 @@ grpc_cc_library(
"absl/strings", "absl/strings",
"absl/types:optional", "absl/types:optional",
"absl/types:span", "absl/types:span",
"upb_base_lib",
"upb_collections_lib", "upb_collections_lib",
"upb_lib", "upb_lib",
], ],
@ -1213,6 +1214,7 @@ grpc_cc_library(
"include/grpcpp/security/alts_util.h", "include/grpcpp/security/alts_util.h",
], ],
external_deps = [ external_deps = [
"upb_base_lib",
"upb_collections_lib", "upb_collections_lib",
"upb_lib", "upb_lib",
], ],
@ -1602,6 +1604,7 @@ grpc_cc_library(
"//src/core:slice_refcount", "//src/core:slice_refcount",
"//src/core:socket_mutator", "//src/core:socket_mutator",
"//src/core:stats_data", "//src/core:stats_data",
"//src/core:status_flag",
"//src/core:status_helper", "//src/core:status_helper",
"//src/core:strerror", "//src/core:strerror",
"//src/core:thread_quota", "//src/core:thread_quota",
@ -1930,6 +1933,7 @@ grpc_cc_library(
"absl/synchronization", "absl/synchronization",
"absl/memory", "absl/memory",
"absl/types:optional", "absl/types:optional",
"upb_base_lib",
"upb_lib", "upb_lib",
"protobuf_headers", "protobuf_headers",
"absl/container:inlined_vector", "absl/container:inlined_vector",
@ -2004,6 +2008,7 @@ grpc_cc_library(
"absl/synchronization", "absl/synchronization",
"absl/types:optional", "absl/types:optional",
"absl/memory", "absl/memory",
"upb_base_lib",
"upb_lib", "upb_lib",
"absl/strings:str_format", "absl/strings:str_format",
"protobuf_headers", "protobuf_headers",
@ -2173,6 +2178,7 @@ grpc_cc_library(
"absl/strings", "absl/strings",
"absl/time", "absl/time",
"absl/types:optional", "absl/types:optional",
"upb_base_lib",
"upb_lib", "upb_lib",
], ],
language = "c++", language = "c++",
@ -2936,6 +2942,7 @@ grpc_cc_library(
"//src/core:lib/resolver/endpoint_addresses.h", "//src/core:lib/resolver/endpoint_addresses.h",
], ],
external_deps = [ external_deps = [
"absl/functional:function_ref",
"absl/status", "absl/status",
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
@ -3063,6 +3070,7 @@ grpc_cc_library(
"absl/strings:cord", "absl/strings:cord",
"absl/types:optional", "absl/types:optional",
"absl/types:variant", "absl/types:variant",
"upb_base_lib",
"upb_collections_lib", "upb_collections_lib",
"upb_lib", "upb_lib",
], ],
@ -3673,7 +3681,9 @@ grpc_cc_library(
"absl/strings", "absl/strings",
"absl/strings:str_format", "absl/strings:str_format",
"absl/types:optional", "absl/types:optional",
"upb_base_lib",
"upb_lib", "upb_lib",
"upb_mem_lib",
"upb_textformat_lib", "upb_textformat_lib",
"upb_json_lib", "upb_json_lib",
"upb_reflection", "upb_reflection",
@ -3748,9 +3758,9 @@ grpc_cc_library(
hdrs = ["//src/core:ext/filters/client_channel/resolver/fake/fake_resolver.h"], hdrs = ["//src/core:ext/filters/client_channel/resolver/fake/fake_resolver.h"],
external_deps = [ external_deps = [
"absl/base:core_headers", "absl/base:core_headers",
"absl/status",
"absl/status:statusor",
"absl/strings", "absl/strings",
"absl/time",
"absl/types:optional",
], ],
language = "c++", language = "c++",
visibility = [ visibility = [
@ -3760,7 +3770,6 @@ grpc_cc_library(
deps = [ deps = [
"config", "config",
"debug_location", "debug_location",
"endpoint_addresses",
"gpr", "gpr",
"grpc_public_hdrs", "grpc_public_hdrs",
"grpc_resolver", "grpc_resolver",
@ -3769,7 +3778,6 @@ grpc_cc_library(
"uri_parser", "uri_parser",
"work_serializer", "work_serializer",
"//src/core:channel_args", "//src/core:channel_args",
"//src/core:grpc_service_config",
"//src/core:notification", "//src/core:notification",
"//src/core:ref_counted", "//src/core:ref_counted",
"//src/core:useful", "//src/core:useful",
@ -3863,8 +3871,10 @@ grpc_cc_library(
deps = [ deps = [
"gpr", "gpr",
"grpc_base", "grpc_base",
"ref_counted_ptr",
"//src/core:error", "//src/core:error",
"//src/core:hpack_constants", "//src/core:hpack_constants",
"//src/core:ref_counted",
"//src/core:slice", "//src/core:slice",
"//src/core:status_helper", "//src/core:status_helper",
], ],

1569
CMakeLists.txt generated

File diff suppressed because it is too large Load Diff

1469
Makefile generated

File diff suppressed because it is too large Load Diff

@ -1,3 +0,0 @@
# Top level ownership
@markdroth **/OWNERS
@a11r **/OWNERS

1520
Package.swift generated

File diff suppressed because it is too large Load Diff

@ -66,7 +66,7 @@ pip_install(
requirements = "@com_github_grpc_grpc//:requirements.bazel.txt", requirements = "@com_github_grpc_grpc//:requirements.bazel.txt",
) )
load("@upb//bazel:system_python.bzl", "system_python") load("@com_google_protobuf//bazel:system_python.bzl", "system_python")
system_python( system_python(
name = "system_python", name = "system_python",
@ -77,9 +77,9 @@ load("@system_python//:pip.bzl", "pip_parse")
pip_parse( pip_parse(
name = "pip_deps", name = "pip_deps",
requirements = "@upb//python:requirements.txt", requirements = "@com_google_protobuf//python:requirements.txt",
requirements_overrides = { requirements_overrides = {
"3.11": "@upb//python:requirements_311.txt", "3.11": "@com_google_protobuf//python:requirements_311.txt",
}, },
) )

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/_metadata.py.template`!!! # AUTO-GENERATED FROM `$REPO_ROOT/templates/_metadata.py.template`!!!
__version__ = """1.60.0.dev0""" __version__ = """1.61.0.dev0"""

@ -16,6 +16,47 @@
"""Dictionary of tags to experiments so we know when to test different experiments.""" """Dictionary of tags to experiments so we know when to test different experiments."""
EXPERIMENT_ENABLES = {
"call_status_override_on_cancellation": "call_status_override_on_cancellation",
"canary_client_privacy": "canary_client_privacy",
"client_idleness": "client_idleness",
"client_privacy": "client_privacy",
"event_engine_client": "event_engine_client",
"event_engine_dns": "event_engine_dns",
"event_engine_listener": "event_engine_listener",
"free_large_allocator": "free_large_allocator",
"http2_stats_fix": "http2_stats_fix",
"keepalive_fix": "keepalive_fix",
"keepalive_server_fix": "keepalive_server_fix",
"memory_pressure_controller": "memory_pressure_controller",
"monitoring_experiment": "monitoring_experiment",
"multiping": "multiping",
"overload_protection": "overload_protection",
"peer_state_based_framing": "peer_state_based_framing",
"pending_queue_cap": "pending_queue_cap",
"pick_first_happy_eyeballs": "pick_first_happy_eyeballs",
"promise_based_client_call": "promise_based_client_call",
"promise_based_inproc_transport": "promise_based_inproc_transport",
"promise_based_server_call": "promise_based_server_call",
"red_max_concurrent_streams": "red_max_concurrent_streams",
"registered_method_lookup_in_transport": "registered_method_lookup_in_transport",
"registered_methods_map": "registered_methods_map",
"rfc_max_concurrent_streams": "rfc_max_concurrent_streams",
"round_robin_delegate_to_pick_first": "round_robin_delegate_to_pick_first",
"rstpit": "rstpit",
"schedule_cancellation_over_write": "schedule_cancellation_over_write",
"server_privacy": "server_privacy",
"tcp_frame_size_tuning": "tcp_frame_size_tuning",
"tcp_rcv_lowat": "tcp_rcv_lowat",
"trace_record_callops": "trace_record_callops",
"unconstrained_max_quota_buffer_size": "unconstrained_max_quota_buffer_size",
"work_serializer_clears_time_cache": "work_serializer_clears_time_cache",
"work_serializer_dispatch": "work_serializer_dispatch",
"write_size_policy": "write_size_policy",
"write_size_cap": "write_size_cap,write_size_policy",
"wrr_delegate_to_pick_first": "wrr_delegate_to_pick_first",
}
EXPERIMENTS = { EXPERIMENTS = {
"windows": { "windows": {
"dbg": { "dbg": {
@ -65,17 +106,9 @@ EXPERIMENTS = {
], ],
}, },
"on": { "on": {
"bad_client_test": [
"block_excessive_requests_before_settings_ack",
"tarpit",
],
"core_end2end_test": [ "core_end2end_test": [
"event_engine_listener", "event_engine_listener",
], ],
"cpp_end2end_test": [
"chttp2_batch_requests",
"chttp2_offload_on_rst_stream",
],
"cpp_lb_end2end_test": [ "cpp_lb_end2end_test": [
"pick_first_happy_eyeballs", "pick_first_happy_eyeballs",
"round_robin_delegate_to_pick_first", "round_robin_delegate_to_pick_first",
@ -85,9 +118,6 @@ EXPERIMENTS = {
"event_engine_listener", "event_engine_listener",
], ],
"flow_control_test": [ "flow_control_test": [
"chttp2_batch_requests",
"chttp2_offload_on_rst_stream",
"lazier_stream_updates",
"overload_protection", "overload_protection",
"write_size_cap", "write_size_cap",
"write_size_policy", "write_size_policy",
@ -155,23 +185,12 @@ EXPERIMENTS = {
], ],
}, },
"on": { "on": {
"bad_client_test": [
"block_excessive_requests_before_settings_ack",
"tarpit",
],
"cpp_end2end_test": [
"chttp2_batch_requests",
"chttp2_offload_on_rst_stream",
],
"cpp_lb_end2end_test": [ "cpp_lb_end2end_test": [
"pick_first_happy_eyeballs", "pick_first_happy_eyeballs",
"round_robin_delegate_to_pick_first", "round_robin_delegate_to_pick_first",
"wrr_delegate_to_pick_first", "wrr_delegate_to_pick_first",
], ],
"flow_control_test": [ "flow_control_test": [
"chttp2_batch_requests",
"chttp2_offload_on_rst_stream",
"lazier_stream_updates",
"overload_protection", "overload_protection",
"write_size_cap", "write_size_cap",
"write_size_policy", "write_size_policy",
@ -249,17 +268,9 @@ EXPERIMENTS = {
], ],
}, },
"on": { "on": {
"bad_client_test": [
"block_excessive_requests_before_settings_ack",
"tarpit",
],
"core_end2end_test": [ "core_end2end_test": [
"event_engine_listener", "event_engine_listener",
], ],
"cpp_end2end_test": [
"chttp2_batch_requests",
"chttp2_offload_on_rst_stream",
],
"cpp_lb_end2end_test": [ "cpp_lb_end2end_test": [
"pick_first_happy_eyeballs", "pick_first_happy_eyeballs",
"round_robin_delegate_to_pick_first", "round_robin_delegate_to_pick_first",
@ -269,9 +280,6 @@ EXPERIMENTS = {
"event_engine_listener", "event_engine_listener",
], ],
"flow_control_test": [ "flow_control_test": [
"chttp2_batch_requests",
"chttp2_offload_on_rst_stream",
"lazier_stream_updates",
"overload_protection", "overload_protection",
"write_size_cap", "write_size_cap",
"write_size_policy", "write_size_policy",

@ -15,7 +15,7 @@
licenses(["notice"]) licenses(["notice"])
package( package(
default_visibility = ["//visibility:public"] default_visibility = ["//visibility:public"],
) )
# This is needed for the dependency on google_cloud_cpp to work. # This is needed for the dependency on google_cloud_cpp to work.

@ -29,11 +29,11 @@ Contains macros used throughout the repo.
load("//bazel:cc_grpc_library.bzl", "cc_grpc_library") load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
load("//bazel:copts.bzl", "GRPC_DEFAULT_COPTS") load("//bazel:copts.bzl", "GRPC_DEFAULT_COPTS")
load("//bazel:experiments.bzl", "EXPERIMENTS") load("//bazel:experiments.bzl", "EXPERIMENTS", "EXPERIMENT_ENABLES")
load("//bazel:test_experiments.bzl", "TEST_EXPERIMENTS") load("//bazel:test_experiments.bzl", "TEST_EXPERIMENTS", "TEST_EXPERIMENT_ENABLES")
load("@upb//bazel:upb_proto_library.bzl", "upb_proto_library", "upb_proto_reflection_library")
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test") load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load("@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl", "ios_test_runner") load("@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl", "ios_test_runner")
load("@com_google_protobuf//bazel:upb_proto_library.bzl", "upb_proto_library", "upb_proto_reflection_library")
# The set of pollers to test against if a test exercises polling # The set of pollers to test against if a test exercises polling
POLLERS = ["epoll1", "poll"] POLLERS = ["epoll1", "poll"]
@ -204,8 +204,8 @@ def grpc_cc_library(
includes = [ includes = [
"api/include", "api/include",
"include", "include",
"src/core/ext/upb-generated", # Once upb code-gen issue is resolved, remove this. "src/core/ext/upb-gen", # Once upb code-gen issue is resolved, remove this.
"src/core/ext/upbdefs-generated", # Once upb code-gen issue is resolved, remove this. "src/core/ext/upbdefs-gen", # Once upb code-gen issue is resolved, remove this.
], ],
alwayslink = alwayslink, alwayslink = alwayslink,
data = data, data = data,
@ -418,6 +418,7 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
return tags return tags
experiment_config = list(poller_config) experiment_config = list(poller_config)
experiment_enables = {k: v for k, v in EXPERIMENT_ENABLES.items() + TEST_EXPERIMENT_ENABLES.items()}
for mode, config in mode_config.items(): for mode, config in mode_config.items():
enabled_tags, disabled_tags = config enabled_tags, disabled_tags = config
if enabled_tags != None: if enabled_tags != None:
@ -426,7 +427,7 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
config = dict(config) config = dict(config)
config["name"] = config["name"] + "@experiment=" + experiment config["name"] = config["name"] + "@experiment=" + experiment
env = dict(config["env"]) env = dict(config["env"])
env["GRPC_EXPERIMENTS"] = experiment env["GRPC_EXPERIMENTS"] = experiment_enables[experiment]
env["GRPC_CI_EXPERIMENTS"] = "1" env["GRPC_CI_EXPERIMENTS"] = "1"
config["env"] = env config["env"] = env
tags = config["tags"] + ["experiment_variation"] tags = config["tags"] + ["experiment_variation"]

@ -22,42 +22,57 @@ def grpc_deps():
native.bind( native.bind(
name = "upb_lib", name = "upb_lib",
actual = "@upb//:upb", actual = "@com_google_protobuf//upb",
)
native.bind(
name = "upb_amalgamation_lib",
actual = "@com_google_protobuf//upb:amalgamation",
)
native.bind(
name = "upb_base_lib",
actual = "@com_google_protobuf//upb/base",
) )
native.bind( native.bind(
name = "upb_collections_lib", name = "upb_collections_lib",
actual = "@upb//:collections", actual = "@com_google_protobuf//upb/collections",
)
native.bind(
name = "upb_mem_lib",
actual = "@com_google_protobuf//upb/mem",
) )
native.bind( native.bind(
name = "upb_reflection", name = "upb_reflection",
actual = "@upb//:reflection", actual = "@com_google_protobuf//upb:reflection",
) )
native.bind( native.bind(
name = "upb_lib_descriptor", name = "upb_lib_descriptor",
actual = "@upb//:descriptor_upb_proto", actual = "@com_google_protobuf//upb:descriptor_upb_proto",
) )
native.bind( native.bind(
name = "upb_lib_descriptor_reflection", name = "upb_lib_descriptor_reflection",
actual = "@upb//:descriptor_upb_proto_reflection", actual = "@com_google_protobuf//upb:descriptor_upb_proto_reflection",
) )
native.bind( native.bind(
name = "upb_textformat_lib", name = "upb_textformat_lib",
actual = "@upb//:textformat", actual = "@com_google_protobuf//upb/text",
) )
native.bind( native.bind(
name = "upb_json_lib", name = "upb_json_lib",
actual = "@upb//:json", actual = "@com_google_protobuf//upb/json",
) )
native.bind( native.bind(
name = "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", name = "upb_generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
actual = "@upb//:generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", actual = "@com_google_protobuf//upb:generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
) )
native.bind( native.bind(
@ -243,12 +258,12 @@ def grpc_deps():
if "com_google_protobuf" not in native.existing_rules(): if "com_google_protobuf" not in native.existing_rules():
http_archive( http_archive(
name = "com_google_protobuf", name = "com_google_protobuf",
sha256 = "660ce016f987550bc1ccec4a6ee4199afb871799b696227098e3641476a7d566", sha256 = "7ed5fc41fe1614e551025f8e14b79b026a015b3ed337d38920c586f3ea35d818",
strip_prefix = "protobuf-b2b7a51158418f41cff0520894836c15b1738721", strip_prefix = "protobuf-6b5d8db01fe47478e8d400f550e797e6230d464e",
urls = [ urls = [
# https://github.com/protocolbuffers/protobuf/commits/v24.3 # https://github.com/protocolbuffers/protobuf/commits/v25.0
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/protobuf/archive/b2b7a51158418f41cff0520894836c15b1738721.tar.gz", "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/protobuf/archive/6b5d8db01fe47478e8d400f550e797e6230d464e.tar.gz",
"https://github.com/protocolbuffers/protobuf/archive/b2b7a51158418f41cff0520894836c15b1738721.tar.gz", "https://github.com/protocolbuffers/protobuf/archive/6b5d8db01fe47478e8d400f550e797e6230d464e.tar.gz",
], ],
patches = [ patches = [
"@com_github_grpc_grpc//third_party:protobuf.patch", "@com_github_grpc_grpc//third_party:protobuf.patch",
@ -380,18 +395,6 @@ def grpc_deps():
], ],
) )
if "upb" not in native.existing_rules():
http_archive(
name = "upb",
sha256 = "5147e0ab6a28421d1e49004f4a205d84f06b924585e15eaa884cfe13289165b7",
strip_prefix = "upb-42cd08932e364a4cde35033b73f15c30250d7c2e",
urls = [
# https://github.com/protocolbuffers/upb/commits/24.x
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/upb/archive/42cd08932e364a4cde35033b73f15c30250d7c2e.tar.gz",
"https://github.com/protocolbuffers/upb/archive/42cd08932e364a4cde35033b73f15c30250d7c2e.tar.gz",
],
)
if "envoy_api" not in native.existing_rules(): if "envoy_api" not in native.existing_rules():
http_archive( http_archive(
name = "envoy_api", name = "envoy_api",
@ -509,11 +512,11 @@ def grpc_deps():
if "io_opentelemetry_cpp" not in native.existing_rules(): if "io_opentelemetry_cpp" not in native.existing_rules():
http_archive( http_archive(
name = "io_opentelemetry_cpp", name = "io_opentelemetry_cpp",
sha256 = "f30cd88bf898a5726d245eba882b8e81012021eb00df34109f4dfb203f005cea", sha256 = "149f076cc7a79bbd3a3c34fb3ab61d3a3e8dcfe2b9596f79153e17123c32f897",
strip_prefix = "opentelemetry-cpp-1.11.0", strip_prefix = "opentelemetry-cpp-064fef0d871c57ffac6739d3311659a5770a9db4",
urls = [ urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/open-telemetry/opentelemetry-cpp/archive/refs/tags/v1.11.0.tar.gz", "https://storage.googleapis.com/grpc-bazel-mirror/github.com/open-telemetry/opentelemetry-cpp/archive/064fef0d871c57ffac6739d3311659a5770a9db4.tar.gz",
"https://github.com/open-telemetry/opentelemetry-cpp/archive/refs/tags/v1.11.0.tar.gz", "https://github.com/open-telemetry/opentelemetry-cpp/archive/064fef0d871c57ffac6739d3311659a5770a9db4.tar.gz",
], ],
) )

@ -22,7 +22,6 @@ load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
load("@envoy_api//bazel:repositories.bzl", "api_dependencies") load("@envoy_api//bazel:repositories.bzl", "api_dependencies")
load("@google_cloud_cpp//bazel:google_cloud_cpp_deps.bzl", "google_cloud_cpp_deps") load("@google_cloud_cpp//bazel:google_cloud_cpp_deps.bzl", "google_cloud_cpp_deps")
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@upb//bazel:workspace_deps.bzl", "upb_deps")
def grpc_extra_deps(ignore_version_differences = False): def grpc_extra_deps(ignore_version_differences = False):
"""Loads the extra dependencies. """Loads the extra dependencies.
@ -49,8 +48,6 @@ def grpc_extra_deps(ignore_version_differences = False):
""" """
protobuf_deps() protobuf_deps()
upb_deps()
api_dependencies() api_dependencies()
go_rules_dependencies() go_rules_dependencies()

@ -1,2 +1 @@
6.3.2 6.4.0
5.4.1

@ -16,6 +16,13 @@
"""Dictionary of tags to experiments so we know when to test different experiments.""" """Dictionary of tags to experiments so we know when to test different experiments."""
TEST_EXPERIMENT_ENABLES = {
"test_experiment_1": "test_experiment_1",
"test_experiment_2": "test_experiment_2",
"test_experiment_3": "test_experiment_3",
"test_experiment_4": "test_experiment_4",
}
TEST_EXPERIMENTS = { TEST_EXPERIMENTS = {
"windows": { "windows": {
"dbg": { "dbg": {

@ -57,17 +57,9 @@ function upload {
# upload "github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz" # upload "github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz"
# bazel binaries used by the tools/bazel wrapper script # bazel binaries used by the tools/bazel wrapper script
upload github.com/bazelbuild/bazel/releases/download/5.4.1/bazel-5.4.1-linux-x86_64 upload github.com/bazelbuild/bazel/releases/download/6.4.0/bazel-6.4.0-linux-x86_64
upload github.com/bazelbuild/bazel/releases/download/5.4.1/bazel-5.4.1-darwin-x86_64 upload github.com/bazelbuild/bazel/releases/download/6.4.0/bazel-6.4.0-darwin-x86_64
upload github.com/bazelbuild/bazel/releases/download/5.4.1/bazel-5.4.1-windows-x86_64.exe upload github.com/bazelbuild/bazel/releases/download/6.4.0/bazel-6.4.0-windows-x86_64.exe
upload github.com/bazelbuild/bazel/releases/download/6.1.2/bazel-6.1.2-linux-x86_64
upload github.com/bazelbuild/bazel/releases/download/6.1.2/bazel-6.1.2-darwin-x86_64
upload github.com/bazelbuild/bazel/releases/download/6.1.2/bazel-6.1.2-windows-x86_64.exe
upload github.com/bazelbuild/bazel/releases/download/6.3.2/bazel-6.3.2-linux-x86_64
upload github.com/bazelbuild/bazel/releases/download/6.3.2/bazel-6.3.2-darwin-x86_64
upload github.com/bazelbuild/bazel/releases/download/6.3.2/bazel-6.3.2-windows-x86_64.exe
# Collect the github archives to mirror from grpc_deps.bzl # Collect the github archives to mirror from grpc_deps.bzl
grep -o '"https://github.com/[^"]*"' bazel/grpc_deps.bzl | sed 's/^"https:\/\///' | sed 's/"$//' | while read -r line ; do grep -o '"https://github.com/[^"]*"' bazel/grpc_deps.bzl | sed 's/^"https:\/\///' | sed 's/"$//' | while read -r line ; do

File diff suppressed because it is too large Load Diff

@ -13,5 +13,5 @@
# limitations under the License. # limitations under the License.
module GrpcBuildConfig module GrpcBuildConfig
CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-36.dll' CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-37.dll'
end end

@ -12,11 +12,11 @@ settings:
'#08': Use "-preN" suffixes to identify pre-release versions '#08': Use "-preN" suffixes to identify pre-release versions
'#09': Per-language overrides are possible with (eg) ruby_version tag here '#09': Per-language overrides are possible with (eg) ruby_version tag here
'#10': See the expand_version.py for all the quirks here '#10': See the expand_version.py for all the quirks here
core_version: 36.0.0 core_version: 37.0.0
csharp_major_version: 2 csharp_major_version: 2
g_stands_for: gjallarhorn g_stands_for: grand
protobuf_version: 3.24.3 protobuf_version: 3.25.0
version: 1.60.0-dev version: 1.61.0-dev
configs: configs:
asan: asan:
CC: clang CC: clang
@ -149,8 +149,8 @@ defaults:
CFLAGS: -g CFLAGS: -g
COREFLAGS: -fno-exceptions COREFLAGS: -fno-exceptions
CPPFLAGS: -g -Wall -Wextra -DOSATOMIC_USE_INLINED=1 -Ithird_party/abseil-cpp -Ithird_party/re2 CPPFLAGS: -g -Wall -Wextra -DOSATOMIC_USE_INLINED=1 -Ithird_party/abseil-cpp -Ithird_party/re2
-Ithird_party/upb -Isrc/core/ext/upb-generated -Isrc/core/ext/upbdefs-generated -Ithird_party/upb -Isrc/core/ext/upb-gen -Isrc/core/ext/upbdefs-gen -Ithird_party/utf8_range
-Ithird_party/utf8_range -Ithird_party/xxhash -Ithird_party/xxhash
LDFLAGS: -g LDFLAGS: -g
zlib: zlib:
CFLAGS: -fvisibility=hidden CFLAGS: -fvisibility=hidden

@ -15,6 +15,6 @@
set(UPB_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/upb) set(UPB_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/upb)
set(_gRPC_UPB_INCLUDE_DIR "${UPB_ROOT_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/third_party/utf8_range") set(_gRPC_UPB_INCLUDE_DIR "${UPB_ROOT_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/third_party/utf8_range")
set(_gRPC_UPB_GRPC_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/core/ext/upb-generated" "${CMAKE_CURRENT_SOURCE_DIR}/src/core/ext/upbdefs-generated") set(_gRPC_UPB_GRPC_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/core/ext/upb-gen" "${CMAKE_CURRENT_SOURCE_DIR}/src/core/ext/upbdefs-gen")
set(_gRPC_UPB_LIBRARIES upb) set(_gRPC_UPB_LIBRARIES upb)

848
config.m4 generated

@ -6,8 +6,8 @@ if test "$PHP_GRPC" != "no"; then
dnl # --with-grpc -> add include path dnl # --with-grpc -> add include path
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/core/ext/upb-generated) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/core/ext/upb-gen)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/core/ext/upbdefs-generated) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/core/ext/upbdefs-gen)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/abseil-cpp) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/abseil-cpp)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/address_sorting/include) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/address_sorting/include)
@ -156,319 +156,319 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/transport/inproc/inproc_plugin.cc \ src/core/ext/transport/inproc/inproc_plugin.cc \
src/core/ext/transport/inproc/inproc_transport.cc \ src/core/ext/transport/inproc/inproc_transport.cc \
src/core/ext/transport/inproc/legacy_inproc_transport.cc \ src/core/ext/transport/inproc/legacy_inproc_transport.cc \
src/core/ext/upb-generated/envoy/admin/v3/certs.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/certs.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/clusters.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/clusters.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/config_dump.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/config_dump_shared.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/config_dump_shared.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/init_dump.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/init_dump.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/listeners.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/listeners.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/memory.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/memory.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/metrics.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/metrics.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/mutex_stats.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/mutex_stats.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/server_info.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/server_info.upb_minitable.c \
src/core/ext/upb-generated/envoy/admin/v3/tap.upb.c \ src/core/ext/upb-gen/envoy/admin/v3/tap.upb_minitable.c \
src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \ src/core/ext/upb-gen/envoy/annotations/deprecation.upb_minitable.c \
src/core/ext/upb-generated/envoy/annotations/resource.upb.c \ src/core/ext/upb-gen/envoy/annotations/resource.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c \ src/core/ext/upb-gen/envoy/config/accesslog/v3/accesslog.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c \ src/core/ext/upb-gen/envoy/config/bootstrap/v3/bootstrap.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c \ src/core/ext/upb-gen/envoy/config/cluster/v3/circuit_breaker.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c \ src/core/ext/upb-gen/envoy/config/cluster/v3/cluster.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c \ src/core/ext/upb-gen/envoy/config/cluster/v3/filter.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/cluster/v3/outlier_detection.upb.c \ src/core/ext/upb-gen/envoy/config/cluster/v3/outlier_detection.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/common/matcher/v3/matcher.upb.c \ src/core/ext/upb-gen/envoy/config/common/matcher/v3/matcher.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/address.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/address.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/backoff.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/backoff.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/base.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/base.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/config_source.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/event_service_config.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/event_service_config.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/extension.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/extension.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/grpc_method_list.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/grpc_method_list.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/grpc_service.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/health_check.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/http_uri.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/http_uri.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/protocol.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/proxy_protocol.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/resolver.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/resolver.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/socket_option.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/socket_option.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/substitution_format_string.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/core/v3/udp_socket_config.upb.c \ src/core/ext/upb-gen/envoy/config/core/v3/udp_socket_config.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint.upb.c \ src/core/ext/upb-gen/envoy/config/endpoint/v3/endpoint.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint_components.upb.c \ src/core/ext/upb-gen/envoy/config/endpoint/v3/endpoint_components.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/endpoint/v3/load_report.upb.c \ src/core/ext/upb-gen/envoy/config/endpoint/v3/load_report.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/listener/v3/api_listener.upb.c \ src/core/ext/upb-gen/envoy/config/listener/v3/api_listener.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c \ src/core/ext/upb-gen/envoy/config/listener/v3/listener.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c \ src/core/ext/upb-gen/envoy/config/listener/v3/listener_components.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.c \ src/core/ext/upb-gen/envoy/config/listener/v3/quic_config.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c \ src/core/ext/upb-gen/envoy/config/listener/v3/udp_listener_config.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/metrics/v3/metrics_service.upb.c \ src/core/ext/upb-gen/envoy/config/metrics/v3/metrics_service.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c \ src/core/ext/upb-gen/envoy/config/metrics/v3/stats.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c \ src/core/ext/upb-gen/envoy/config/overload/v3/overload.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c \ src/core/ext/upb-gen/envoy/config/rbac/v3/rbac.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c \ src/core/ext/upb-gen/envoy/config/route/v3/route.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c \ src/core/ext/upb-gen/envoy/config/route/v3/route_components.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c \ src/core/ext/upb-gen/envoy/config/route/v3/scoped_route.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/tap/v3/common.upb.c \ src/core/ext/upb-gen/envoy/config/tap/v3/common.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/datadog.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/datadog.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/dynamic_ot.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/dynamic_ot.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/http_tracer.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/lightstep.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/lightstep.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/opencensus.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/opencensus.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/opentelemetry.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/opentelemetry.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/service.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/service.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/skywalking.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/skywalking.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/trace.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/trace.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/xray.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/xray.upb_minitable.c \
src/core/ext/upb-generated/envoy/config/trace/v3/zipkin.upb.c \ src/core/ext/upb-gen/envoy/config/trace/v3/zipkin.upb_minitable.c \
src/core/ext/upb-generated/envoy/data/accesslog/v3/accesslog.upb.c \ src/core/ext/upb-gen/envoy/data/accesslog/v3/accesslog.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c \ src/core/ext/upb-gen/envoy/extensions/clusters/aggregate/v3/cluster.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c \ src/core/ext/upb-gen/envoy/extensions/filters/common/fault/v3/fault.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c \ src/core/ext/upb-gen/envoy/extensions/filters/http/fault/v3/fault.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c \ src/core/ext/upb-gen/envoy/extensions/filters/http/rbac/v3/rbac.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \ src/core/ext/upb-gen/envoy/extensions/filters/http/router/v3/router.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/filters/http/stateful_session/v3/stateful_session.upb.c \ src/core/ext/upb-gen/envoy/extensions/filters/http/stateful_session/v3/stateful_session.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \ src/core/ext/upb-gen/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb.c \ src/core/ext/upb-gen/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c \ src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3/common.upb.c \ src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/common/v3/common.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c \ src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c \ src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c \ src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \ src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/cert.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c \ src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/common.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c \ src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/secret.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.c \ src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/tls.upb_minitable.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.upb.c \ src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.upb_minitable.c \
src/core/ext/upb-generated/envoy/service/discovery/v3/ads.upb.c \ src/core/ext/upb-gen/envoy/service/discovery/v3/ads.upb_minitable.c \
src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.c \ src/core/ext/upb-gen/envoy/service/discovery/v3/discovery.upb_minitable.c \
src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c \ src/core/ext/upb-gen/envoy/service/load_stats/v3/lrs.upb_minitable.c \
src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c \ src/core/ext/upb-gen/envoy/service/status/v3/csds.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/http/v3/cookie.upb.c \ src/core/ext/upb-gen/envoy/type/http/v3/cookie.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/http/v3/path_transformation.upb.c \ src/core/ext/upb-gen/envoy/type/http/v3/path_transformation.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/filter_state.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/filter_state.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/http_inputs.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/metadata.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/node.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/number.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/path.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/regex.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/status_code_input.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/status_code_input.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/string.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/struct.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c \ src/core/ext/upb-gen/envoy/type/matcher/v3/value.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c \ src/core/ext/upb-gen/envoy/type/metadata/v3/metadata.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c \ src/core/ext/upb-gen/envoy/type/tracing/v3/custom_tag.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/hash_policy.upb.c \ src/core/ext/upb-gen/envoy/type/v3/hash_policy.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/http.upb.c \ src/core/ext/upb-gen/envoy/type/v3/http.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/http_status.upb.c \ src/core/ext/upb-gen/envoy/type/v3/http_status.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/percent.upb.c \ src/core/ext/upb-gen/envoy/type/v3/percent.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/range.upb.c \ src/core/ext/upb-gen/envoy/type/v3/range.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/ratelimit_strategy.upb.c \ src/core/ext/upb-gen/envoy/type/v3/ratelimit_strategy.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/ratelimit_unit.upb.c \ src/core/ext/upb-gen/envoy/type/v3/ratelimit_unit.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.c \ src/core/ext/upb-gen/envoy/type/v3/semantic_version.upb_minitable.c \
src/core/ext/upb-generated/envoy/type/v3/token_bucket.upb.c \ src/core/ext/upb-gen/envoy/type/v3/token_bucket.upb_minitable.c \
src/core/ext/upb-generated/google/api/annotations.upb.c \ src/core/ext/upb-gen/google/api/annotations.upb_minitable.c \
src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c \ src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb_minitable.c \
src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c \ src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.c \
src/core/ext/upb-generated/google/api/http.upb.c \ src/core/ext/upb-gen/google/api/http.upb_minitable.c \
src/core/ext/upb-generated/google/api/httpbody.upb.c \ src/core/ext/upb-gen/google/api/httpbody.upb_minitable.c \
src/core/ext/upb-generated/google/protobuf/any.upb.c \ src/core/ext/upb-gen/google/protobuf/any.upb_minitable.c \
src/core/ext/upb-generated/google/protobuf/descriptor.upb.c \ src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c \
src/core/ext/upb-generated/google/protobuf/duration.upb.c \ src/core/ext/upb-gen/google/protobuf/duration.upb_minitable.c \
src/core/ext/upb-generated/google/protobuf/empty.upb.c \ src/core/ext/upb-gen/google/protobuf/empty.upb_minitable.c \
src/core/ext/upb-generated/google/protobuf/struct.upb.c \ src/core/ext/upb-gen/google/protobuf/struct.upb_minitable.c \
src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \ src/core/ext/upb-gen/google/protobuf/timestamp.upb_minitable.c \
src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \ src/core/ext/upb-gen/google/protobuf/wrappers.upb_minitable.c \
src/core/ext/upb-generated/google/rpc/status.upb.c \ src/core/ext/upb-gen/google/rpc/status.upb_minitable.c \
src/core/ext/upb-generated/opencensus/proto/trace/v1/trace_config.upb.c \ src/core/ext/upb-gen/opencensus/proto/trace/v1/trace_config.upb_minitable.c \
src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c \ src/core/ext/upb-gen/src/proto/grpc/gcp/altscontext.upb_minitable.c \
src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c \ src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb_minitable.c \
src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c \ src/core/ext/upb-gen/src/proto/grpc/gcp/transport_security_common.upb_minitable.c \
src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \ src/core/ext/upb-gen/src/proto/grpc/health/v1/health.upb_minitable.c \
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \ src/core/ext/upb-gen/src/proto/grpc/lb/v1/load_balancer.upb_minitable.c \
src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls.upb.c \ src/core/ext/upb-gen/src/proto/grpc/lookup/v1/rls.upb_minitable.c \
src/core/ext/upb-generated/src/proto/grpc/lookup/v1/rls_config.upb.c \ src/core/ext/upb-gen/src/proto/grpc/lookup/v1/rls_config.upb_minitable.c \
src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \ src/core/ext/upb-gen/udpa/annotations/migrate.upb_minitable.c \
src/core/ext/upb-generated/udpa/annotations/security.upb.c \ src/core/ext/upb-gen/udpa/annotations/security.upb_minitable.c \
src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \ src/core/ext/upb-gen/udpa/annotations/sensitive.upb_minitable.c \
src/core/ext/upb-generated/udpa/annotations/status.upb.c \ src/core/ext/upb-gen/udpa/annotations/status.upb_minitable.c \
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \ src/core/ext/upb-gen/udpa/annotations/versioning.upb_minitable.c \
src/core/ext/upb-generated/validate/validate.upb.c \ src/core/ext/upb-gen/validate/validate.upb_minitable.c \
src/core/ext/upb-generated/xds/annotations/v3/migrate.upb.c \ src/core/ext/upb-gen/xds/annotations/v3/migrate.upb_minitable.c \
src/core/ext/upb-generated/xds/annotations/v3/security.upb.c \ src/core/ext/upb-gen/xds/annotations/v3/security.upb_minitable.c \
src/core/ext/upb-generated/xds/annotations/v3/sensitive.upb.c \ src/core/ext/upb-gen/xds/annotations/v3/sensitive.upb_minitable.c \
src/core/ext/upb-generated/xds/annotations/v3/status.upb.c \ src/core/ext/upb-gen/xds/annotations/v3/status.upb_minitable.c \
src/core/ext/upb-generated/xds/annotations/v3/versioning.upb.c \ src/core/ext/upb-gen/xds/annotations/v3/versioning.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/authority.upb.c \ src/core/ext/upb-gen/xds/core/v3/authority.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/cidr.upb.c \ src/core/ext/upb-gen/xds/core/v3/cidr.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c \ src/core/ext/upb-gen/xds/core/v3/collection_entry.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/context_params.upb.c \ src/core/ext/upb-gen/xds/core/v3/context_params.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/extension.upb.c \ src/core/ext/upb-gen/xds/core/v3/extension.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/resource.upb.c \ src/core/ext/upb-gen/xds/core/v3/resource.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c \ src/core/ext/upb-gen/xds/core/v3/resource_locator.upb_minitable.c \
src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c \ src/core/ext/upb-gen/xds/core/v3/resource_name.upb_minitable.c \
src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c \ src/core/ext/upb-gen/xds/data/orca/v3/orca_load_report.upb_minitable.c \
src/core/ext/upb-generated/xds/service/orca/v3/orca.upb.c \ src/core/ext/upb-gen/xds/service/orca/v3/orca.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/cel.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/cel.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/domain.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/domain.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/http_inputs.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/http_inputs.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/ip.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/ip.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/matcher.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/matcher.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/range.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/range.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/regex.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/regex.upb_minitable.c \
src/core/ext/upb-generated/xds/type/matcher/v3/string.upb.c \ src/core/ext/upb-gen/xds/type/matcher/v3/string.upb_minitable.c \
src/core/ext/upb-generated/xds/type/v3/cel.upb.c \ src/core/ext/upb-gen/xds/type/v3/cel.upb_minitable.c \
src/core/ext/upb-generated/xds/type/v3/range.upb.c \ src/core/ext/upb-gen/xds/type/v3/range.upb_minitable.c \
src/core/ext/upb-generated/xds/type/v3/typed_struct.upb.c \ src/core/ext/upb-gen/xds/type/v3/typed_struct.upb_minitable.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/certs.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/certs.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/clusters.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/clusters.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/config_dump.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump_shared.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/config_dump_shared.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/init_dump.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/init_dump.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/listeners.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/listeners.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/memory.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/memory.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/metrics.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/metrics.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/mutex_stats.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/mutex_stats.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/server_info.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/server_info.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/admin/v3/tap.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/admin/v3/tap.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/annotations/deprecation.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/annotations/resource.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/accesslog/v3/accesslog.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/bootstrap/v3/bootstrap.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/cluster/v3/circuit_breaker.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/cluster/v3/cluster.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/cluster/v3/filter.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/cluster/v3/outlier_detection.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/cluster/v3/outlier_detection.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/common/matcher/v3/matcher.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/common/matcher/v3/matcher.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/address.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/address.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/backoff.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/backoff.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/base.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/base.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/config_source.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/config_source.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/event_service_config.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/event_service_config.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/extension.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/extension.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/grpc_method_list.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/grpc_method_list.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/grpc_service.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/grpc_service.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/health_check.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/health_check.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/http_uri.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/http_uri.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/protocol.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/proxy_protocol.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/resolver.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/resolver.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/socket_option.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/socket_option.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/substitution_format_string.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/substitution_format_string.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/core/v3/udp_socket_config.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/core/v3/udp_socket_config.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/endpoint/v3/endpoint.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/endpoint/v3/endpoint.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/endpoint/v3/endpoint_components.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/endpoint/v3/endpoint_components.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/endpoint/v3/load_report.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/endpoint/v3/load_report.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/listener/v3/api_listener.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/listener/v3/api_listener.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/listener/v3/listener.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/listener/v3/listener_components.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/listener/v3/quic_config.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/listener/v3/udp_listener_config.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/metrics/v3/metrics_service.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/metrics/v3/metrics_service.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/metrics/v3/stats.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/overload/v3/overload.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/rbac/v3/rbac.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/route/v3/route.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/route/v3/route_components.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/route/v3/scoped_route.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/tap/v3/common.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/tap/v3/common.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/datadog.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/datadog.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/dynamic_ot.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/dynamic_ot.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/http_tracer.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/lightstep.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/lightstep.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/opencensus.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/opencensus.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/opentelemetry.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/opentelemetry.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/service.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/service.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/skywalking.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/skywalking.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/trace.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/trace.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/xray.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/xray.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/zipkin.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/config/trace/v3/zipkin.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/data/accesslog/v3/accesslog.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/data/accesslog/v3/accesslog.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/filters/http/router/v3/router.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/http/stateful_session/v3/stateful_session.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/filters/http/stateful_session/v3/stateful_session.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/http/stateful_session/cookie/v3/cookie.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/http/stateful_session/cookie/v3/cookie.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/secret.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/secret.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/service/discovery/v3/ads.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/service/discovery/v3/ads.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/service/discovery/v3/discovery.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/service/discovery/v3/discovery.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/service/load_stats/v3/lrs.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/service/status/v3/csds.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/http/v3/cookie.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/http/v3/cookie.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/http/v3/path_transformation.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/http/v3/path_transformation.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/filter_state.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/filter_state.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/http_inputs.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/metadata.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/node.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/number.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/path.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/regex.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/status_code_input.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/status_code_input.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/string.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/struct.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/matcher/v3/value.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/metadata/v3/metadata.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/tracing/v3/custom_tag.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/hash_policy.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/hash_policy.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/http.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/http.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/http_status.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/http_status.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/percent.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/percent.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/range.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/range.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/ratelimit_strategy.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/ratelimit_strategy.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/ratelimit_unit.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/ratelimit_unit.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/semantic_version.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/semantic_version.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/type/v3/token_bucket.upbdefs.c \ src/core/ext/upbdefs-gen/envoy/type/v3/token_bucket.upbdefs.c \
src/core/ext/upbdefs-generated/google/api/annotations.upbdefs.c \ src/core/ext/upbdefs-gen/google/api/annotations.upbdefs.c \
src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.c \ src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/checked.upbdefs.c \
src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.c \ src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.c \
src/core/ext/upbdefs-generated/google/api/http.upbdefs.c \ src/core/ext/upbdefs-gen/google/api/http.upbdefs.c \
src/core/ext/upbdefs-generated/google/api/httpbody.upbdefs.c \ src/core/ext/upbdefs-gen/google/api/httpbody.upbdefs.c \
src/core/ext/upbdefs-generated/google/protobuf/any.upbdefs.c \ src/core/ext/upbdefs-gen/google/protobuf/any.upbdefs.c \
src/core/ext/upbdefs-generated/google/protobuf/descriptor.upbdefs.c \ src/core/ext/upbdefs-gen/google/protobuf/descriptor.upbdefs.c \
src/core/ext/upbdefs-generated/google/protobuf/duration.upbdefs.c \ src/core/ext/upbdefs-gen/google/protobuf/duration.upbdefs.c \
src/core/ext/upbdefs-generated/google/protobuf/empty.upbdefs.c \ src/core/ext/upbdefs-gen/google/protobuf/empty.upbdefs.c \
src/core/ext/upbdefs-generated/google/protobuf/struct.upbdefs.c \ src/core/ext/upbdefs-gen/google/protobuf/struct.upbdefs.c \
src/core/ext/upbdefs-generated/google/protobuf/timestamp.upbdefs.c \ src/core/ext/upbdefs-gen/google/protobuf/timestamp.upbdefs.c \
src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c \ src/core/ext/upbdefs-gen/google/protobuf/wrappers.upbdefs.c \
src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c \ src/core/ext/upbdefs-gen/google/rpc/status.upbdefs.c \
src/core/ext/upbdefs-generated/opencensus/proto/trace/v1/trace_config.upbdefs.c \ src/core/ext/upbdefs-gen/opencensus/proto/trace/v1/trace_config.upbdefs.c \
src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1/rls_config.upbdefs.c \ src/core/ext/upbdefs-gen/src/proto/grpc/lookup/v1/rls_config.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/migrate.upbdefs.c \ src/core/ext/upbdefs-gen/udpa/annotations/migrate.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c \ src/core/ext/upbdefs-gen/udpa/annotations/security.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c \ src/core/ext/upbdefs-gen/udpa/annotations/sensitive.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \ src/core/ext/upbdefs-gen/udpa/annotations/status.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \ src/core/ext/upbdefs-gen/udpa/annotations/versioning.upbdefs.c \
src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \ src/core/ext/upbdefs-gen/validate/validate.upbdefs.c \
src/core/ext/upbdefs-generated/xds/annotations/v3/migrate.upbdefs.c \ src/core/ext/upbdefs-gen/xds/annotations/v3/migrate.upbdefs.c \
src/core/ext/upbdefs-generated/xds/annotations/v3/security.upbdefs.c \ src/core/ext/upbdefs-gen/xds/annotations/v3/security.upbdefs.c \
src/core/ext/upbdefs-generated/xds/annotations/v3/sensitive.upbdefs.c \ src/core/ext/upbdefs-gen/xds/annotations/v3/sensitive.upbdefs.c \
src/core/ext/upbdefs-generated/xds/annotations/v3/status.upbdefs.c \ src/core/ext/upbdefs-gen/xds/annotations/v3/status.upbdefs.c \
src/core/ext/upbdefs-generated/xds/annotations/v3/versioning.upbdefs.c \ src/core/ext/upbdefs-gen/xds/annotations/v3/versioning.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/authority.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/cidr.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/cidr.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/collection_entry.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/context_params.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/extension.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/extension.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/resource.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/resource_locator.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c \ src/core/ext/upbdefs-gen/xds/core/v3/resource_name.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/cel.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/cel.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/domain.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/domain.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/http_inputs.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/http_inputs.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/ip.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/ip.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/matcher.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/matcher.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/range.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/range.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/regex.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/regex.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/matcher/v3/string.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/matcher/v3/string.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/v3/cel.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/v3/cel.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/v3/range.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/v3/range.upbdefs.c \
src/core/ext/upbdefs-generated/xds/type/v3/typed_struct.upbdefs.c \ src/core/ext/upbdefs-gen/xds/type/v3/typed_struct.upbdefs.c \
src/core/ext/xds/certificate_provider_store.cc \ src/core/ext/xds/certificate_provider_store.cc \
src/core/ext/xds/file_watcher_certificate_provider_factory.cc \ src/core/ext/xds/file_watcher_certificate_provider_factory.cc \
src/core/ext/xds/xds_api.cc \ src/core/ext/xds/xds_api.cc \
@ -534,12 +534,12 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/event_engine/default_event_engine_factory.cc \ src/core/lib/event_engine/default_event_engine_factory.cc \
src/core/lib/event_engine/event_engine.cc \ src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/forkable.cc \ src/core/lib/event_engine/forkable.cc \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc \ src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc \
src/core/lib/event_engine/posix_engine/ev_poll_posix.cc \ src/core/lib/event_engine/posix_engine/ev_poll_posix.cc \
src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc \ src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc \
src/core/lib/event_engine/posix_engine/internal_errqueue.cc \ src/core/lib/event_engine/posix_engine/internal_errqueue.cc \
src/core/lib/event_engine/posix_engine/lockfree_event.cc \ src/core/lib/event_engine/posix_engine/lockfree_event.cc \
src/core/lib/event_engine/posix_engine/native_dns_resolver.cc \
src/core/lib/event_engine/posix_engine/posix_endpoint.cc \ src/core/lib/event_engine/posix_engine/posix_endpoint.cc \
src/core/lib/event_engine/posix_engine/posix_engine.cc \ src/core/lib/event_engine/posix_engine/posix_engine.cc \
src/core/lib/event_engine/posix_engine/posix_engine_listener.cc \ src/core/lib/event_engine/posix_engine/posix_engine_listener.cc \
@ -565,6 +565,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/event_engine/time_util.cc \ src/core/lib/event_engine/time_util.cc \
src/core/lib/event_engine/trace.cc \ src/core/lib/event_engine/trace.cc \
src/core/lib/event_engine/utils.cc \ src/core/lib/event_engine/utils.cc \
src/core/lib/event_engine/windows/grpc_polled_fd_windows.cc \
src/core/lib/event_engine/windows/iocp.cc \ src/core/lib/event_engine/windows/iocp.cc \
src/core/lib/event_engine/windows/win_socket.cc \ src/core/lib/event_engine/windows/win_socket.cc \
src/core/lib/event_engine/windows/windows_endpoint.cc \ src/core/lib/event_engine/windows/windows_endpoint.cc \
@ -608,6 +609,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/gprpp/load_file.cc \ src/core/lib/gprpp/load_file.cc \
src/core/lib/gprpp/mpscq.cc \ src/core/lib/gprpp/mpscq.cc \
src/core/lib/gprpp/per_cpu.cc \ src/core/lib/gprpp/per_cpu.cc \
src/core/lib/gprpp/posix/directory_reader.cc \
src/core/lib/gprpp/posix/env.cc \ src/core/lib/gprpp/posix/env.cc \
src/core/lib/gprpp/posix/stat.cc \ src/core/lib/gprpp/posix/stat.cc \
src/core/lib/gprpp/posix/thd.cc \ src/core/lib/gprpp/posix/thd.cc \
@ -619,6 +621,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/gprpp/time_averaged_stats.cc \ src/core/lib/gprpp/time_averaged_stats.cc \
src/core/lib/gprpp/time_util.cc \ src/core/lib/gprpp/time_util.cc \
src/core/lib/gprpp/validation_errors.cc \ src/core/lib/gprpp/validation_errors.cc \
src/core/lib/gprpp/windows/directory_reader.cc \
src/core/lib/gprpp/windows/env.cc \ src/core/lib/gprpp/windows/env.cc \
src/core/lib/gprpp/windows/stat.cc \ src/core/lib/gprpp/windows/stat.cc \
src/core/lib/gprpp/windows/thd.cc \ src/core/lib/gprpp/windows/thd.cc \
@ -1292,9 +1295,6 @@ if test "$PHP_GRPC" != "no"; then
third_party/re2/util/rune.cc \ third_party/re2/util/rune.cc \
third_party/re2/util/strutil.cc \ third_party/re2/util/strutil.cc \
third_party/upb/upb/base/status.c \ third_party/upb/upb/base/status.c \
third_party/upb/upb/collections/array.c \
third_party/upb/upb/collections/map.c \
third_party/upb/upb/collections/map_sorter.c \
third_party/upb/upb/hash/common.c \ third_party/upb/upb/hash/common.c \
third_party/upb/upb/json/decode.c \ third_party/upb/upb/json/decode.c \
third_party/upb/upb/json/encode.c \ third_party/upb/upb/json/encode.c \
@ -1305,6 +1305,9 @@ if test "$PHP_GRPC" != "no"; then
third_party/upb/upb/mem/alloc.c \ third_party/upb/upb/mem/alloc.c \
third_party/upb/upb/mem/arena.c \ third_party/upb/upb/mem/arena.c \
third_party/upb/upb/message/accessors.c \ third_party/upb/upb/message/accessors.c \
third_party/upb/upb/message/array.c \
third_party/upb/upb/message/map.c \
third_party/upb/upb/message/map_sorter.c \
third_party/upb/upb/message/message.c \ third_party/upb/upb/message/message.c \
third_party/upb/upb/mini_descriptor/build_enum.c \ third_party/upb/upb/mini_descriptor/build_enum.c \
third_party/upb/upb/mini_descriptor/decode.c \ third_party/upb/upb/mini_descriptor/decode.c \
@ -1314,7 +1317,6 @@ if test "$PHP_GRPC" != "no"; then
third_party/upb/upb/mini_table/extension_registry.c \ third_party/upb/upb/mini_table/extension_registry.c \
third_party/upb/upb/mini_table/internal/message.c \ third_party/upb/upb/mini_table/internal/message.c \
third_party/upb/upb/mini_table/message.c \ third_party/upb/upb/mini_table/message.c \
third_party/upb/upb/reflection/def_builder.c \
third_party/upb/upb/reflection/def_pool.c \ third_party/upb/upb/reflection/def_pool.c \
third_party/upb/upb/reflection/def_type.c \ third_party/upb/upb/reflection/def_type.c \
third_party/upb/upb/reflection/desc_state.c \ third_party/upb/upb/reflection/desc_state.c \
@ -1324,6 +1326,8 @@ if test "$PHP_GRPC" != "no"; then
third_party/upb/upb/reflection/extension_range.c \ third_party/upb/upb/reflection/extension_range.c \
third_party/upb/upb/reflection/field_def.c \ third_party/upb/upb/reflection/field_def.c \
third_party/upb/upb/reflection/file_def.c \ third_party/upb/upb/reflection/file_def.c \
third_party/upb/upb/reflection/internal/def_builder.c \
third_party/upb/upb/reflection/internal/strdup2.c \
third_party/upb/upb/reflection/message.c \ third_party/upb/upb/reflection/message.c \
third_party/upb/upb/reflection/message_def.c \ third_party/upb/upb/reflection/message_def.c \
third_party/upb/upb/reflection/message_reserved_range.c \ third_party/upb/upb/reflection/message_reserved_range.c \
@ -1344,7 +1348,7 @@ if test "$PHP_GRPC" != "no"; then
-D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0 \ -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0 \
-DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1 \ -DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1 \
-DGRPC_XDS_USER_AGENT_NAME_SUFFIX='"\"PHP\""' \ -DGRPC_XDS_USER_AGENT_NAME_SUFFIX='"\"PHP\""' \
-DGRPC_XDS_USER_AGENT_VERSION_SUFFIX='"\"1.60.0dev\""') -DGRPC_XDS_USER_AGENT_VERSION_SUFFIX='"\"1.61.0dev\""')
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/backend_metrics) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/backend_metrics)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/census) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/census)
@ -1387,106 +1391,106 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/inproc) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/inproc)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/admin/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/admin/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/annotations) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/annotations)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/accesslog/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/accesslog/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/bootstrap/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/bootstrap/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/cluster/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/cluster/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/common/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/common/matcher/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/core/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/core/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/endpoint/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/endpoint/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/listener/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/listener/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/metrics/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/metrics/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/overload/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/overload/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/rbac/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/rbac/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/route/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/route/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/tap/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/tap/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/trace/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/config/trace/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/data/accesslog/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/data/accesslog/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/clusters/aggregate/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/filters/common/fault/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/filters/http/fault/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/filters/http/rbac/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/filters/http/router/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/stateful_session/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/filters/http/stateful_session/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/filters/network/http_connection_manager/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/http/stateful_session/cookie/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/http/stateful_session/cookie/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/common/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/common/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/pick_first/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/ring_hash/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/wrr_locality/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/discovery/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/service/discovery/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/load_stats/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/service/load_stats/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/status/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/service/status/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/http/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/type/http/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/type/matcher/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/metadata/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/type/metadata/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/tracing/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/type/tracing/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/envoy/type/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/google/api) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/google/api)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/google/api/expr/v1alpha1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/google/api/expr/v1alpha1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/google/protobuf) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/google/protobuf)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/google/rpc) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/google/rpc)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/opencensus/proto/trace/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/opencensus/proto/trace/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/gcp) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/src/proto/grpc/gcp)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/health/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/src/proto/grpc/health/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/lb/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/src/proto/grpc/lb/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/lookup/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/src/proto/grpc/lookup/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/annotations) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/udpa/annotations)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/validate) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/validate)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/annotations/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/xds/annotations/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/core/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/xds/core/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/data/orca/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/xds/data/orca/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/service/orca/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/xds/service/orca/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/type/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/xds/type/matcher/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/type/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-gen/xds/type/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/admin/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/admin/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/annotations) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/annotations)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/accesslog/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/accesslog/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/bootstrap/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/cluster/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/cluster/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/common/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/common/matcher/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/core/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/core/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/endpoint/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/endpoint/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/listener/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/listener/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/metrics/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/metrics/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/overload/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/overload/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/rbac/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/rbac/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/route/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/route/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/tap/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/tap/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/trace/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/config/trace/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/data/accesslog/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/data/accesslog/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/clusters/aggregate/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/filters/common/fault/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/fault/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/rbac/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/router/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/stateful_session/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/stateful_session/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/filters/network/http_connection_manager/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/http/stateful_session/cookie/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/http/stateful_session/cookie/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/discovery/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/service/discovery/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/service/load_stats/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/status/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/service/status/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/http/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/type/http/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/type/matcher/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/metadata/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/type/metadata/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/tracing/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/type/tracing/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/envoy/type/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/api) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/google/api)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/protobuf) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/google/protobuf)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/rpc) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/google/rpc)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/opencensus/proto/trace/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/opencensus/proto/trace/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/src/proto/grpc/lookup/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/src/proto/grpc/lookup/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/udpa/annotations) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/udpa/annotations)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/validate) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/validate)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/annotations/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/xds/annotations/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/core/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/xds/core/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/type/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/xds/type/matcher/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/type/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-gen/xds/type/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/xds) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/xds)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/address_utils) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/address_utils)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/backoff) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/backoff)
@ -1634,7 +1638,6 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/third_party/re2/re2) PHP_ADD_BUILD_DIR($ext_builddir/third_party/re2/re2)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/re2/util) PHP_ADD_BUILD_DIR($ext_builddir/third_party/re2/util)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/base) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/base)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/collections)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/hash) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/hash)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/json) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/json)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/lex) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/lex)
@ -1645,6 +1648,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/mini_table) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/mini_table)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/mini_table/internal) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/mini_table/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/reflection) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/reflection)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/reflection/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/text) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/text)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/wire) PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb/wire)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/utf8_range) PHP_ADD_BUILD_DIR($ext_builddir/third_party/utf8_range)

1118
config.w32 generated

File diff suppressed because it is too large Load Diff

@ -34,10 +34,13 @@ grpc_extra_deps()
## Supported Versions ## Supported Versions
In general, gRPC supports building with the latest patch release of the two most gRPC supports building with the latest stable release of Bazel,
recent LTS versions of Bazel. However individual releases may have a broader as well as the previous major version release for at least 6 months
after it transitions into maintenance mode.
This is consistent with the supported build systems of
[the Google Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support).
However individual releases may have a broader
compatibility range. The currently supported versions are captured by the compatibility range. The currently supported versions are captured by the
following list: following list:
- [`6.3.2`](https://github.com/bazelbuild/bazel/releases/tag/6.3.2) - [`6.4.0`](https://github.com/bazelbuild/bazel/releases/tag/6.4.0)
- [`5.4.1`](https://github.com/bazelbuild/bazel/releases/tag/5.4.1)

@ -59,4 +59,5 @@
- 1.57 'g' stands for ['grounded'](https://github.com/grpc/grpc/tree/v1.57.x) - 1.57 'g' stands for ['grounded'](https://github.com/grpc/grpc/tree/v1.57.x)
- 1.58 'g' stands for ['goku'](https://github.com/grpc/grpc/tree/v1.58.x) - 1.58 'g' stands for ['goku'](https://github.com/grpc/grpc/tree/v1.58.x)
- 1.59 'g' stands for ['generative'](https://github.com/grpc/grpc/tree/v1.59.x) - 1.59 'g' stands for ['generative'](https://github.com/grpc/grpc/tree/v1.59.x)
- 1.60 'g' stands for ['gjallarhorn'](https://github.com/grpc/grpc/tree/master) - 1.60 'g' stands for ['gjallarhorn'](https://github.com/grpc/grpc/tree/v1.60.x)
- 1.61 'g' stands for ['grand'](https://github.com/grpc/grpc/tree/master)

@ -62,12 +62,12 @@ DNS](https://github.com/grpc/proposal/blob/master/A2-service-configs-in-dns.md).
Here is an example service config in protobuf form: Here is an example service config in protobuf form:
``` ```textproto
{ {
// Use round_robin LB policy. # Use round_robin LB policy.
load_balancing_config: { round_robin: {} } load_balancing_config: { round_robin: {} }
// This method config applies to method "foo/bar" and to all methods # This method config applies to method "foo/bar" and to all methods
// of service "baz". # of service "baz".
method_config: { method_config: {
name: { name: {
service: "foo" service: "foo"
@ -76,7 +76,7 @@ Here is an example service config in protobuf form:
name: { name: {
service: "baz" service: "baz"
} }
// Default timeout for matching methods. # Default timeout for matching methods.
timeout: { timeout: {
seconds: 1 seconds: 1
nanos: 1 nanos: 1
@ -87,7 +87,7 @@ Here is an example service config in protobuf form:
Here is the same example service config in JSON form: Here is the same example service config in JSON form:
``` ```json
{ {
"loadBalancingConfig": [ { "round_robin": {} } ], "loadBalancingConfig": [ { "round_robin": {} } ],
"methodConfig": [ "methodConfig": [

@ -0,0 +1,42 @@
# Copyright 2023 the 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.
licenses(["notice"])
cc_binary(
name = "crashing_greeter_client",
srcs = ["crashing_greeter_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"//:grpc++",
"//examples/protos:helloworld_cc_grpc",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
],
)
cc_binary(
name = "greeter_callback_server_admin",
srcs = ["greeter_callback_server_admin.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"//:grpc++",
"//:grpc++_reflection",
"//:grpcpp_admin",
"//examples/protos:helloworld_cc_grpc",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
"@com_google_absl//absl/strings:str_format",
],
)

@ -0,0 +1,132 @@
# gRPC C++ Debugging Example
This example demonstrates a handful of ways you can debug your gRPC C++ applications.
## Enabling Trace Logs
gRPC allows you to configure more detailed log output for various aspects of gRPC behavior. The tracing log generation might have a large overhead and result in significantly larger log file sizes, especially when you try to trace transport or timer_check. But it is a powerful tool in your debugging toolkit.
### The Most Verbose Logging
Specify environment variables, then run your application:
```
GRPC_VERBOSITY=debug
GRPC_TRACE=all
```
For more granularity, please see
[environment_variables](https://github.com/grpc/grpc/blob/master/doc/environment_variables.md).
### Debug Transport Protocol
```
GRPC_VERBOSITY=debug
GRPC_TRACE=tcp,http,secure_endpoint,transport_security
```
### Debug Connection Behavior
```
GRPC_VERBOSITY=debug
GRPC_TRACE=call_error,connectivity_state,pick_first,round_robin,glb
```
## GDB and other debuggers
`gdb` (and the like) are tools that lets you inspect your application while it is running, view stack traces on exceptions, pause and step through code at specified points or under certain conditions, etc. See https://www.sourceware.org/gdb/
### Inspecting errors
```
bazel build --config=dbg examples/cpp/debugging:crashing_greeter_client
gdb -ex run \
--args ./bazel-bin/examples/cpp/debugging/crashing_greeter_client \
--crash_on_errors=true \
--target=localhork:50051
```
Once the exception is thrown, you can use `bt` to see the stack trace and examine the crash, `info threads` to get the set of threads, etc. See the [GDB documentation](https://sourceware.org/gdb/current/onlinedocs/gdb.html/) for a more complete list of available features and commands.
### Breaking inside a function
After building the application above, this will break inside gRPC generated stub code:
```
gdb -ex 'b helloworld::Greeter::Stub::SayHello' \
-ex run \
--args ./bazel-bin/examples/cpp/debugging/crashing_greeter_client \
--crash_on_errors=true \
--target=localhork:50051
```
## gRPC Admin Interface: Live Channel Tracing
The [gRPC Admin Service](https://github.com/grpc/proposal/blob/master/A38-admin-interface-api.md)
provides a convenient API in each gRPC language to improve the usability of
creating a gRPC server with admin services to expose states in the gRPC library.
This includes channelz, which is a channel tracing feature; it tracks statistics
like how many messages have been sent, how many of them failed, what are the
connected sockets. See the [Channelz design doc](https://github.com/grpc/proposal/blob/master/A14-channelz.md).
### Integrating the gRPC Admin Service Into Your Server
As seen in the `greeter_callback_admin_server` target, you canenable admin services by using the `AddAdminServices` method.
```
grpc::ServerBuilder builder;
grpc::AddAdminServices(&builder);
builder.AddListeningPort(":50051", grpc::ServerCredentials(...));
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
```
### Using grpcdebug
grpcdebug is a tool created to access the metrics from channelz and health services.
#### Installing the grpcdebug tool
The source code is located in a github project
[grpc-ecosystem/grpcdebug](https://github.com/grpc-ecosystem/grpcdebug). You
can either download [the latest built version]
(https://github.com/grpc-ecosystem/grpcdebug/releases/latest) (recommended) or
follow the README.md to build it yourself.
#### Running the grpcdebug tool
##### Usage
`grpcdebug <target address> [flags] channelz <command> [argument]`
| Command | Argument | Description |
| :--------- | :------------------: | :------------------------------------------------ |
| channel | \<channel id or URL> | Display channel states in a human readable way. |
| channels | | Lists client channels for the target application. |
| server | \<server ID> | Displays server state in a human readable way. |
| servers | | Lists servers in a human readable way. |
| socket | \<socket ID> | Displays socket states in a human readable way. |
| subchannel | \<id> | Display subchannel states in human readable way. |
Generally, you will start with either `servers` or `channels` and then work down
to the details
##### Getting overall server info
To begin with, build and run the server binary in the background
```
bazel build --config=dbg examples/cpp/debugging:all
./bazel-bin/examples/cpp/debugging/greeter_callback_server_admin&
```
You can then inspect the server
```bash
grpcdebug localhost:50051 channelz servers
```
This will show you the server ids with their activity
```text
Server ID Listen Addresses Calls(Started/Succeeded/Failed) Last Call Started
1 [[::]:50051] 38/34/3 now
```
For more information about `grpcdebug` features, please see [the grpcdebug documentation](https://github.com/grpc-ecosystem/grpcdebug)

@ -0,0 +1,92 @@
// Copyright 2023 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <iostream>
#include <memory>
#include <string>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
ABSL_FLAG(bool, crash_on_errors, false,
"Crash the application on client errors");
ABSL_FLAG(std::string, target, "localhost:50051", "Server address");
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// The actual RPC.
Status status = stub_->SayHello(&context, request, &reply);
// Act upon the status of the actual RPC.
if (absl::GetFlag(FLAGS_crash_on_errors)) {
assert(status.ok());
}
if (status.ok()) {
return reply.message();
} else {
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint specified by
// the argument "--target=" which is the only expected argument.
// We indicate that the channel isn't authenticated (use of
// InsecureChannelCredentials()).
GreeterClient greeter(grpc::CreateChannel(
absl::GetFlag(FLAGS_target), grpc::InsecureChannelCredentials()));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;
return 0;
}

@ -0,0 +1,86 @@
// Copyright 2023 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <iostream>
#include <memory>
#include <string>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/str_format.h"
#include <grpcpp/ext/admin_services.h>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
ABSL_FLAG(uint16_t, port, 50051, "Server port for the service");
using grpc::CallbackServerContext;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerUnaryReactor;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::CallbackService {
ServerUnaryReactor* SayHello(CallbackServerContext* context,
const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
ServerUnaryReactor* reactor = context->DefaultReactor();
reactor->Finish(Status::OK);
return reactor;
}
};
void RunServer(uint16_t port) {
std::string server_address = absl::StrFormat("0.0.0.0:%d", port);
GreeterServiceImpl service;
grpc::EnableDefaultHealthCheckService(true);
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
// Enable gRPC Admin Services
grpc::AddAdminServices(&builder);
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
RunServer(absl::GetFlag(FLAGS_port));
return 0;
}

@ -24,3 +24,25 @@ grpc_fuzz_test(
], ],
deps = ["//src/core:write_size_policy"], deps = ["//src/core:write_size_policy"],
) )
grpc_fuzz_test(
name = "hpack_encoder_timeout_test",
srcs = ["hpack_encoder_timeout_test.cc"],
external_deps = [
"absl/random",
"fuzztest",
"fuzztest_main",
"gtest",
],
deps = [
"//:grpc_base",
"//:hpack_encoder",
"//:hpack_parser",
"//:ref_counted_ptr",
"//src/core:arena",
"//src/core:memory_quota",
"//src/core:resource_quota",
"//src/core:slice_buffer",
"//src/core:time",
],
)

@ -0,0 +1,79 @@
// Copyright 2023 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.
// Test to verify Fuzztest integration
#include <grpc/event_engine/memory_allocator.h>
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include <memory>
#include <optional>
#include "absl/random/random.h"
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/lib/resource_quota/memory_quota.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
namespace grpc_core {
void EncodeTimeouts(std::vector<uint32_t> timeouts) {
absl::BitGen bitgen;
ScopedTimeCache time_cache;
time_cache.TestOnlySetNow(Timestamp::ProcessEpoch());
hpack_encoder_detail::TimeoutCompressorImpl timeout_compressor;
HPackCompressor compressor;
HPackParser parser;
MemoryAllocator memory_allocator = MemoryAllocator(
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
auto arena = MakeScopedArena(1024, &memory_allocator);
for (size_t i = 0; i < timeouts.size(); i++) {
SliceBuffer encoded;
hpack_encoder_detail::Encoder encoder(&compressor, false, encoded);
timeout_compressor.EncodeWith(
"grpc-timeout",
Timestamp::ProcessEpoch() + Duration::Milliseconds(timeouts[i]),
&encoder);
grpc_metadata_batch b(arena.get());
const uint32_t kMetadataSizeLimit = 3u * 1024 * 1024 * 1024;
parser.BeginFrame(
&b, kMetadataSizeLimit, kMetadataSizeLimit, HPackParser::Boundary::None,
HPackParser::Priority::None,
HPackParser::LogInfo{1, HPackParser::LogInfo::kHeaders, false});
for (size_t j = 0; j < encoded.Count(); j++) {
EXPECT_TRUE(parser
.Parse(encoded.c_slice_at(j), j == encoded.Count() - 1,
bitgen, nullptr)
.ok());
}
auto parsed = b.get(GrpcTimeoutMetadata());
ASSERT_TRUE(parsed.has_value());
EXPECT_GE(*parsed,
Timestamp::ProcessEpoch() + Duration::Milliseconds(timeouts[i]));
EXPECT_LE(*parsed, Timestamp::ProcessEpoch() +
Duration::Milliseconds(timeouts[i]) * 1.05 +
Duration::Milliseconds(1));
}
}
FUZZ_TEST(MyTestSuite, EncodeTimeouts);
} // namespace grpc_core

1750
gRPC-C++.podspec generated

File diff suppressed because it is too large Load Diff

2390
gRPC-Core.podspec generated

File diff suppressed because it is too large Load Diff

@ -21,7 +21,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC' s.name = 'gRPC-ProtoRPC'
version = '1.60.0-dev' version = '1.61.0-dev'
s.version = version s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'https://grpc.io' s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary' s.name = 'gRPC-RxLibrary'
version = '1.60.0-dev' version = '1.61.0-dev'
s.version = version s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.' s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'https://grpc.io' s.homepage = 'https://grpc.io'

4
gRPC.podspec generated

@ -20,7 +20,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'gRPC' s.name = 'gRPC'
version = '1.60.0-dev' version = '1.61.0-dev'
s.version = version s.version = version
s.summary = 'gRPC client library for iOS/OSX' s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'https://grpc.io' s.homepage = 'https://grpc.io'
@ -32,6 +32,8 @@ Pod::Spec.new do |s|
:tag => "v#{version}", :tag => "v#{version}",
} }
s.resource = 'src/objective-c/PrivacyInfo.xcprivacy'
name = 'GRPCClient' name = 'GRPCClient'
s.module_name = name s.module_name = name
s.header_dir = name s.header_dir = name

1514
grpc.gemspec generated

File diff suppressed because it is too large Load Diff

807
grpc.gyp generated

File diff suppressed because it is too large Load Diff

@ -79,7 +79,7 @@ namespace experimental {
/// ///
/// ///
/// Blocking EventEngine Callbacks /// Blocking EventEngine Callbacks
/// ----------------------------- /// ------------------------------
/// ///
/// Doing blocking work in EventEngine callbacks is generally not advisable. /// Doing blocking work in EventEngine callbacks is generally not advisable.
/// While gRPC's default EventEngine implementations have some capacity to scale /// While gRPC's default EventEngine implementations have some capacity to scale
@ -90,6 +90,15 @@ namespace experimental {
/// *Best Practice* : Occasional blocking work may be fine, but we do not /// *Best Practice* : Occasional blocking work may be fine, but we do not
/// recommend running a mostly blocking workload in EventEngine threads. /// recommend running a mostly blocking workload in EventEngine threads.
/// ///
///
/// Thread-safety guarantees
/// ------------------------
///
/// All EventEngine methods are guaranteed to be thread-safe, no external
/// synchronization is required to call any EventEngine method. Please note that
/// this does not apply to application callbacks, which may be run concurrently;
/// application state synchronization must be managed by the application.
///
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class EventEngine : public std::enable_shared_from_this<EventEngine> { class EventEngine : public std::enable_shared_from_this<EventEngine> {
public: public:
@ -246,6 +255,45 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
/// values are expected to remain valid for the life of the Endpoint. /// values are expected to remain valid for the life of the Endpoint.
virtual const ResolvedAddress& GetPeerAddress() const = 0; virtual const ResolvedAddress& GetPeerAddress() const = 0;
virtual const ResolvedAddress& GetLocalAddress() const = 0; virtual const ResolvedAddress& GetLocalAddress() const = 0;
/// A method which allows users to query whether an Endpoint implementation
/// supports a specified extension. The name of the extension is provided
/// as an input.
///
/// An extension could be any type with a unique string id. Each extension
/// may support additional capabilities and if the Endpoint implementation
/// supports the queried extension, it should return a valid pointer to the
/// extension type.
///
/// E.g., use case of an EventEngine::Endpoint supporting a custom
/// extension.
///
/// class CustomEndpointExtension {
/// public:
/// static constexpr std::string name = "my.namespace.extension_name";
/// void Process() { ... }
/// }
///
///
/// class CustomEndpoint :
/// public EventEngine::Endpoint, CustomEndpointExtension {
/// public:
/// void* QueryExtension(absl::string_view id) override {
/// if (id == CustomEndpointExtension::name) {
/// return static_cast<CustomEndpointExtension*>(this);
/// }
/// return nullptr;
/// }
/// ...
/// }
///
/// auto ext_ =
/// static_cast<CustomEndpointExtension*>(
/// endpoint->QueryExtension(CustomrEndpointExtension::name));
/// if (ext_ != nullptr) { ext_->Process(); }
///
///
virtual void* QueryExtension(absl::string_view /*id*/) { return nullptr; }
}; };
/// Called when a new connection is established. /// Called when a new connection is established.
@ -405,8 +453,8 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
/// Asynchronously executes a task as soon as possible. /// Asynchronously executes a task as soon as possible.
/// ///
/// \a Closures scheduled with \a Run cannot be cancelled. The \a closure will /// \a Closures passed to \a Run cannot be cancelled. The \a closure will not
/// not be deleted after it has been run, ownership remains with the caller. /// be deleted after it has been run, ownership remains with the caller.
/// ///
/// Implementations must not execute the closure in the calling thread before /// Implementations must not execute the closure in the calling thread before
/// \a Run returns. For example, if the caller must release a lock before the /// \a Run returns. For example, if the caller must release a lock before the
@ -415,9 +463,9 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
virtual void Run(Closure* closure) = 0; virtual void Run(Closure* closure) = 0;
/// Asynchronously executes a task as soon as possible. /// Asynchronously executes a task as soon as possible.
/// ///
/// \a Closures scheduled with \a Run cannot be cancelled. Unlike the /// \a Closures passed to \a Run cannot be cancelled. Unlike the overloaded \a
/// overloaded \a Closure alternative, the absl::AnyInvocable version's \a /// Closure alternative, the absl::AnyInvocable version's \a closure will be
/// closure will be deleted by the EventEngine after the closure has been run. /// deleted by the EventEngine after the closure has been run.
/// ///
/// This version of \a Run may be less performant than the \a Closure version /// This version of \a Run may be less performant than the \a Closure version
/// in some scenarios. This overload is useful in situations where performance /// in some scenarios. This overload is useful in situations where performance
@ -453,13 +501,12 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
absl::AnyInvocable<void()> closure) = 0; absl::AnyInvocable<void()> closure) = 0;
/// Request cancellation of a task. /// Request cancellation of a task.
/// ///
/// If the associated closure has already been scheduled to run, it will not /// If the associated closure cannot be cancelled for any reason, this
/// be cancelled, and this function will return false. /// function will return false.
/// ///
/// If the associated closure has not been scheduled to run, it will be /// If the associated closure can be cancelled, the associated callback will
/// cancelled, and this method will return true. The associated /// never be run, and this method will return true. If the callback type was
/// absl::AnyInvocable or \a Closure* will not be called. If the closure type /// an absl::AnyInvocable, it will be destroyed before the method returns.
/// was an absl::AnyInvocable, it will be destroyed before the method returns.
virtual bool Cancel(TaskHandle handle) = 0; virtual bool Cancel(TaskHandle handle) = 0;
}; };

@ -50,6 +50,12 @@ class MemoryAllocatorImpl
/// request.max() inclusively. /// request.max() inclusively.
virtual size_t Reserve(MemoryRequest request) = 0; virtual size_t Reserve(MemoryRequest request) = 0;
/// Allocate a slice, using MemoryRequest to size the number of returned
/// bytes. For a variable length request, check the returned slice length to
/// verify how much memory was allocated. Takes care of reserving memory for
/// any relevant control structures also.
virtual grpc_slice MakeSlice(MemoryRequest request) = 0;
/// Release some bytes that were previously reserved. /// Release some bytes that were previously reserved.
/// If more bytes are released than were reserved, we will have undefined /// If more bytes are released than were reserved, we will have undefined
/// behavior. /// behavior.

@ -134,7 +134,9 @@ class MemoryAllocator {
/// bytes. For a variable length request, check the returned slice length to /// bytes. For a variable length request, check the returned slice length to
/// verify how much memory was allocated. Takes care of reserving memory for /// verify how much memory was allocated. Takes care of reserving memory for
/// any relevant control structures also. /// any relevant control structures also.
grpc_slice MakeSlice(MemoryRequest request); grpc_slice MakeSlice(MemoryRequest request) {
return allocator_->MakeSlice(request);
}
/// A C++ allocator for containers of T. /// A C++ allocator for containers of T.
template <typename T> template <typename T>

@ -28,7 +28,6 @@
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include <grpc/grpc_security.h> #include <grpc/grpc_security.h>
#include <grpc/support/sync.h>
namespace grpc_core { namespace grpc_core {
namespace experimental { namespace experimental {
@ -68,6 +67,17 @@ class CrlProvider {
absl::StatusOr<std::shared_ptr<CrlProvider>> CreateStaticCrlProvider( absl::StatusOr<std::shared_ptr<CrlProvider>> CreateStaticCrlProvider(
absl::Span<const std::string> crls); absl::Span<const std::string> crls);
// Creates a CRL Provider that periodically and asynchronously reloads a
// directory. The refresh_duration minimum is 60 seconds. The
// reload_error_callback provides a way for the user to specifically log or
// otherwise notify of errors during reloading. Since reloading is asynchronous
// and not on the main codepath, the grpc process will continue to run through
// reloading errors, so this mechanism is an important way to provide signals to
// your monitoring and alerting setup.
absl::StatusOr<std::shared_ptr<CrlProvider>> CreateDirectoryReloaderCrlProvider(
absl::string_view directory, std::chrono::seconds refresh_duration,
std::function<void(absl::Status)> reload_error_callback);
} // namespace experimental } // namespace experimental
} // namespace grpc_core } // namespace grpc_core
@ -81,5 +91,4 @@ absl::StatusOr<std::shared_ptr<CrlProvider>> CreateStaticCrlProvider(
void grpc_tls_credentials_options_set_crl_provider( void grpc_tls_credentials_options_set_crl_provider(
grpc_tls_credentials_options* options, grpc_tls_credentials_options* options,
std::shared_ptr<grpc_core::experimental::CrlProvider> provider); std::shared_ptr<grpc_core::experimental::CrlProvider> provider);
#endif /* GRPC_GRPC_CRL_PROVIDER_H */ #endif /* GRPC_GRPC_CRL_PROVIDER_H */

@ -912,7 +912,10 @@ GRPCAPI void grpc_tls_credentials_options_set_identity_cert_name(
GRPCAPI void grpc_tls_credentials_options_set_cert_request_type( GRPCAPI void grpc_tls_credentials_options_set_cert_request_type(
grpc_tls_credentials_options* options, grpc_tls_credentials_options* options,
grpc_ssl_client_certificate_request_type type); grpc_ssl_client_certificate_request_type type);
/**
/** Deprecated in favor of grpc_tls_credentials_options_set_crl_provider. The
* crl provider interface provides a significantly more flexible approach to
* using CRLs. See gRFC A69 for details.
* EXPERIMENTAL API - Subject to change * EXPERIMENTAL API - Subject to change
* *
* If set, gRPC will read all hashed x.509 CRL files in the directory and * If set, gRPC will read all hashed x.509 CRL files in the directory and

@ -15,7 +15,7 @@
#ifndef GRPC_IMPL_CHANNEL_ARG_NAMES_H #ifndef GRPC_IMPL_CHANNEL_ARG_NAMES_H
#define GRPC_IMPL_CHANNEL_ARG_NAMES_H #define GRPC_IMPL_CHANNEL_ARG_NAMES_H
// IWYU pragma: private, include "third_party/grpc/include/grpc/grpc.h" // IWYU pragma: private, include <grpc/grpc.h>
// IWYU pragma: friend "src/.*" // IWYU pragma: friend "src/.*"
// IWYU pragma: friend "test/.*" // IWYU pragma: friend "test/.*"
@ -384,6 +384,11 @@
* Defaults to 250ms. */ * Defaults to 250ms. */
#define GRPC_ARG_HAPPY_EYEBALLS_CONNECTION_ATTEMPT_DELAY_MS \ #define GRPC_ARG_HAPPY_EYEBALLS_CONNECTION_ATTEMPT_DELAY_MS \
"grpc.happy_eyeballs_connection_attempt_delay_ms" "grpc.happy_eyeballs_connection_attempt_delay_ms"
/** It accepts a MemoryAllocatorFactory as input and If specified, it forces
* the default event engine to use memory allocators created using the provided
* factory. */
#define GRPC_ARG_EVENT_ENGINE_USE_MEMORY_ALLOCATOR_FACTORY \
"grpc.event_engine_use_memory_allocator_factory"
/** \} */ /** \} */
#endif /* GRPC_IMPL_CHANNEL_ARG_NAMES_H */ #endif /* GRPC_IMPL_CHANNEL_ARG_NAMES_H */

@ -74,7 +74,7 @@ struct grpc_slice {
} data; } data;
}; };
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 #define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 7
/** Represents an expandable array of slices, to be interpreted as a /** Represents an expandable array of slices, to be interpreted as a
single item. */ single item. */

@ -99,8 +99,9 @@ class TlsCredentialsOptions {
// verifiers other than the host name verifier is used. // verifiers other than the host name verifier is used.
void set_check_call_host(bool check_call_host); void set_check_call_host(bool check_call_host);
// TODO(zhenlian): This is an experimental API is likely to change in the // Deprecated in favor of set_crl_provider. The
// future. Before de-experiementalizing, verify the API is up to date. // crl provider interface provides a significantly more flexible approach to
// using CRLs. See gRFC A69 for details.
// If set, gRPC will read all hashed x.509 CRL files in the directory and // If set, gRPC will read all hashed x.509 CRL files in the directory and
// enforce the CRL files on all TLS handshakes. Only supported for OpenSSL // enforce the CRL files on all TLS handshakes. Only supported for OpenSSL
// version > 1.1. // version > 1.1.

@ -19,9 +19,9 @@
#define GRPCPP_VERSION_INFO_H #define GRPCPP_VERSION_INFO_H
#define GRPC_CPP_VERSION_MAJOR 1 #define GRPC_CPP_VERSION_MAJOR 1
#define GRPC_CPP_VERSION_MINOR 60 #define GRPC_CPP_VERSION_MINOR 61
#define GRPC_CPP_VERSION_PATCH 0 #define GRPC_CPP_VERSION_PATCH 0
#define GRPC_CPP_VERSION_TAG "dev" #define GRPC_CPP_VERSION_TAG "dev"
#define GRPC_CPP_VERSION_STRING "1.60.0-dev" #define GRPC_CPP_VERSION_STRING "1.61.0-dev"
#endif // GRPCPP_VERSION_INFO_H #endif // GRPCPP_VERSION_INFO_H

1518
package.xml generated

File diff suppressed because it is too large Load Diff

@ -16,3 +16,4 @@ xds-protos==0.0.11
opencensus==0.10.0 opencensus==0.10.0
opencensus-ext-stackdriver==0.8.0 opencensus-ext-stackdriver==0.8.0
absl-py==1.4.0 absl-py==1.4.0
googleapis-common-protos==1.61.0

@ -4,7 +4,7 @@
plugins = Cython.Coverage plugins = Cython.Coverage
[build] [build]
build_base=python_build build_base=pyb
[build_ext] [build_ext]
inplace=1 inplace=1

@ -72,11 +72,9 @@ SSL_INCLUDE = (
os.path.join("third_party", "boringssl-with-bazel", "src", "include"), os.path.join("third_party", "boringssl-with-bazel", "src", "include"),
) )
UPB_INCLUDE = (os.path.join("third_party", "upb"),) UPB_INCLUDE = (os.path.join("third_party", "upb"),)
UPB_GRPC_GENERATED_INCLUDE = ( UPB_GRPC_GENERATED_INCLUDE = (os.path.join("src", "core", "ext", "upb-gen"),)
os.path.join("src", "core", "ext", "upb-generated"),
)
UPBDEFS_GRPC_GENERATED_INCLUDE = ( UPBDEFS_GRPC_GENERATED_INCLUDE = (
os.path.join("src", "core", "ext", "upbdefs-generated"), os.path.join("src", "core", "ext", "upbdefs-gen"),
) )
UTF8_RANGE_INCLUDE = (os.path.join("third_party", "utf8_range"),) UTF8_RANGE_INCLUDE = (os.path.join("third_party", "utf8_range"),)
XXHASH_INCLUDE = (os.path.join("third_party", "xxhash"),) XXHASH_INCLUDE = (os.path.join("third_party", "xxhash"),)

@ -117,10 +117,12 @@ grpc_cc_library(
"lib/experiments/config.h", "lib/experiments/config.h",
"lib/experiments/experiments.h", "lib/experiments/experiments.h",
], ],
defines = select({ defines = select(
"//:grpc_experiments_are_final": ["GRPC_EXPERIMENTS_ARE_FINAL"], {
"//conditions:default": [], "//:grpc_experiments_are_final": ["GRPC_EXPERIMENTS_ARE_FINAL"],
}), "//conditions:default": [],
},
),
external_deps = [ external_deps = [
"absl/functional:any_invocable", "absl/functional:any_invocable",
"absl/strings", "absl/strings",
@ -239,6 +241,27 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "directory_reader",
srcs = [
"lib/gprpp/posix/directory_reader.cc",
"lib/gprpp/windows/directory_reader.cc",
],
hdrs = [
"lib/gprpp/directory_reader.h",
],
external_deps = [
"absl/functional:function_ref",
"absl/status",
"absl/status:statusor",
"absl/strings",
],
deps = [
"//:gpr",
"//:gpr_platform",
],
)
grpc_cc_library( grpc_cc_library(
name = "chunked_vector", name = "chunked_vector",
hdrs = ["lib/gprpp/chunked_vector.h"], hdrs = ["lib/gprpp/chunked_vector.h"],
@ -270,7 +293,9 @@ grpc_cc_library(
"absl/strings:cord", "absl/strings:cord",
"absl/time", "absl/time",
"absl/types:optional", "absl/types:optional",
"upb_base_lib",
"upb_lib", "upb_lib",
"upb_mem_lib",
], ],
language = "c++", language = "c++",
deps = [ deps = [
@ -397,6 +422,23 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "status_flag",
external_deps = [
"absl/status",
"absl/status:statusor",
"absl/types:optional",
],
language = "c++",
public_hdrs = [
"lib/promise/status_flag.h",
],
deps = [
"promise_status",
"//:gpr_platform",
],
)
grpc_cc_library( grpc_cc_library(
name = "map_pipe", name = "map_pipe",
external_deps = ["absl/status"], external_deps = ["absl/status"],
@ -436,6 +478,7 @@ grpc_cc_library(
"arena", "arena",
"construct_destruct", "construct_destruct",
"context", "context",
"poll",
"promise_factory", "promise_factory",
"promise_trace", "promise_trace",
"ref_counted", "ref_counted",
@ -832,6 +875,25 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "inter_activity_latch",
external_deps = [
"absl/base:core_headers",
"absl/strings",
],
language = "c++",
public_hdrs = [
"lib/promise/inter_activity_latch.h",
],
deps = [
"activity",
"poll",
"promise_trace",
"wait_set",
"//:gpr",
],
)
grpc_cc_library( grpc_cc_library(
name = "interceptor_list", name = "interceptor_list",
hdrs = [ hdrs = [
@ -881,6 +943,19 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "promise_mutex",
hdrs = [
"lib/promise/promise_mutex.h",
],
language = "c++",
deps = [
"activity",
"poll",
"//:gpr",
],
)
grpc_cc_library( grpc_cc_library(
name = "inter_activity_pipe", name = "inter_activity_pipe",
hdrs = [ hdrs = [
@ -1088,9 +1163,6 @@ grpc_cc_library(
grpc_cc_library( grpc_cc_library(
name = "event_engine_memory_allocator", name = "event_engine_memory_allocator",
srcs = [
"lib/event_engine/memory_allocator.cc",
],
hdrs = [ hdrs = [
"//:include/grpc/event_engine/internal/memory_allocator_impl.h", "//:include/grpc/event_engine/internal/memory_allocator_impl.h",
"//:include/grpc/event_engine/memory_allocator.h", "//:include/grpc/event_engine/memory_allocator.h",
@ -1100,7 +1172,6 @@ grpc_cc_library(
language = "c++", language = "c++",
deps = [ deps = [
"slice", "slice",
"slice_refcount",
"//:gpr_platform", "//:gpr_platform",
], ],
) )
@ -1146,6 +1217,7 @@ grpc_cc_library(
"race", "race",
"resource_quota_trace", "resource_quota_trace",
"seq", "seq",
"slice_refcount",
"time", "time",
"useful", "useful",
"//:gpr", "//:gpr",
@ -1435,9 +1507,7 @@ grpc_cc_library(
hdrs = [ hdrs = [
"lib/event_engine/forkable.h", "lib/event_engine/forkable.h",
], ],
external_deps = ["absl/base:core_headers"],
deps = [ deps = [
"no_destruct",
"//:config_vars", "//:config_vars",
"//:gpr", "//:gpr",
"//:gpr_platform", "//:gpr_platform",
@ -1467,6 +1537,18 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "event_engine_query_extensions",
hdrs = [
"lib/event_engine/query_extensions.h",
],
external_deps = ["absl/strings"],
deps = [
"//:event_engine_base_hdrs",
"//:gpr_platform",
],
)
grpc_cc_library( grpc_cc_library(
name = "event_engine_work_queue", name = "event_engine_work_queue",
hdrs = [ hdrs = [
@ -1580,9 +1662,9 @@ grpc_cc_library(
"event_engine_trace", "event_engine_trace",
"event_engine_work_queue", "event_engine_work_queue",
"forkable", "forkable",
"no_destruct",
"notification", "notification",
"time", "time",
"useful",
"//:backoff", "//:backoff",
"//:event_engine_base_hdrs", "//:event_engine_base_hdrs",
"//:gpr", "//:gpr",
@ -1643,6 +1725,7 @@ grpc_cc_library(
], ],
deps = [ deps = [
"event_engine_poller", "event_engine_poller",
"forkable",
"posix_event_engine_closure", "posix_event_engine_closure",
"//:event_engine_base_hdrs", "//:event_engine_base_hdrs",
"//:gpr_platform", "//:gpr_platform",
@ -1775,7 +1858,6 @@ grpc_cc_library(
deps = [ deps = [
"event_engine_poller", "event_engine_poller",
"event_engine_time_util", "event_engine_time_util",
"forkable",
"iomgr_port", "iomgr_port",
"posix_event_engine_closure", "posix_event_engine_closure",
"posix_event_engine_event_poller", "posix_event_engine_event_poller",
@ -1813,7 +1895,6 @@ grpc_cc_library(
"common_event_engine_closures", "common_event_engine_closures",
"event_engine_poller", "event_engine_poller",
"event_engine_time_util", "event_engine_time_util",
"forkable",
"iomgr_port", "iomgr_port",
"posix_event_engine_closure", "posix_event_engine_closure",
"posix_event_engine_event_poller", "posix_event_engine_event_poller",
@ -1838,7 +1919,9 @@ grpc_cc_library(
], ],
external_deps = ["absl/strings"], external_deps = ["absl/strings"],
deps = [ deps = [
"forkable",
"iomgr_port", "iomgr_port",
"no_destruct",
"posix_event_engine_event_poller", "posix_event_engine_event_poller",
"posix_event_engine_poller_posix_epoll1", "posix_event_engine_poller_posix_epoll1",
"posix_event_engine_poller_posix_poll", "posix_event_engine_poller_posix_poll",
@ -2052,8 +2135,11 @@ grpc_cc_library(
"event_engine_thread_pool", "event_engine_thread_pool",
"event_engine_trace", "event_engine_trace",
"event_engine_utils", "event_engine_utils",
"forkable",
"init_internally", "init_internally",
"iomgr_port", "iomgr_port",
"native_dns_resolver",
"no_destruct",
"posix_event_engine_base_hdrs", "posix_event_engine_base_hdrs",
"posix_event_engine_closure", "posix_event_engine_closure",
"posix_event_engine_endpoint", "posix_event_engine_endpoint",
@ -2063,7 +2149,9 @@ grpc_cc_library(
"posix_event_engine_tcp_socket_utils", "posix_event_engine_tcp_socket_utils",
"posix_event_engine_timer", "posix_event_engine_timer",
"posix_event_engine_timer_manager", "posix_event_engine_timer_manager",
"ref_counted_dns_resolver_interface",
"useful", "useful",
"//:config_vars",
"//:event_engine_base_hdrs", "//:event_engine_base_hdrs",
"//:gpr", "//:gpr",
"//:grpc_trace", "//:grpc_trace",
@ -2081,6 +2169,7 @@ grpc_cc_library(
"absl/strings", "absl/strings",
], ],
deps = [ deps = [
"ares_resolver",
"channel_args_endpoint_config", "channel_args_endpoint_config",
"common_event_engine_closures", "common_event_engine_closures",
"error", "error",
@ -2090,6 +2179,7 @@ grpc_cc_library(
"event_engine_trace", "event_engine_trace",
"event_engine_utils", "event_engine_utils",
"init_internally", "init_internally",
"iomgr_port",
"posix_event_engine_timer_manager", "posix_event_engine_timer_manager",
"time", "time",
"windows_endpoint", "windows_endpoint",
@ -2290,27 +2380,29 @@ grpc_cc_library(
srcs = ["lib/event_engine/default_event_engine_factory.cc"], srcs = ["lib/event_engine/default_event_engine_factory.cc"],
hdrs = ["lib/event_engine/default_event_engine_factory.h"], hdrs = ["lib/event_engine/default_event_engine_factory.h"],
external_deps = ["absl/memory"], external_deps = ["absl/memory"],
select_deps = [{ select_deps = [
"//:windows": ["windows_event_engine"], {
"//:windows_msvc": ["windows_event_engine"], "//:windows": ["windows_event_engine"],
"//:windows_other": ["windows_event_engine"], "//:windows_msvc": ["windows_event_engine"],
"//:mac": [ "//:windows_other": ["windows_event_engine"],
"posix_event_engine", "//:mac": [
"cf_event_engine", "posix_event_engine",
], "cf_event_engine",
"//:mac_x86_64": [ ],
"posix_event_engine", "//:mac_x86_64": [
"cf_event_engine", "posix_event_engine",
], "cf_event_engine",
"//:mac_arm64": [ ],
"posix_event_engine", "//:mac_arm64": [
"cf_event_engine", "posix_event_engine",
], "cf_event_engine",
"//:ios": ["cf_event_engine"], ],
"//:tvos": ["cf_event_engine"], "//:ios": ["cf_event_engine"],
"//:watchos": ["cf_event_engine"], "//:tvos": ["cf_event_engine"],
"//conditions:default": ["posix_event_engine"], "//:watchos": ["cf_event_engine"],
}], "//conditions:default": ["posix_event_engine"],
},
],
deps = [ deps = [
"//:event_engine_base_hdrs", "//:event_engine_base_hdrs",
"//:gpr_platform", "//:gpr_platform",
@ -2380,16 +2472,53 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "ref_counted_dns_resolver_interface",
hdrs = ["lib/event_engine/ref_counted_dns_resolver_interface.h"],
external_deps = ["absl/strings"],
deps = [
"//:event_engine_base_hdrs",
"//:gpr_platform",
"//:orphanable",
],
)
grpc_cc_library(
name = "native_dns_resolver",
srcs = [
"lib/event_engine/posix_engine/native_dns_resolver.cc",
],
hdrs = [
"lib/event_engine/posix_engine/native_dns_resolver.h",
],
external_deps = [
"absl/functional:any_invocable",
"absl/status",
"absl/status:statusor",
"absl/strings",
"absl/strings:str_format",
],
deps = [
"iomgr_port",
"ref_counted_dns_resolver_interface",
"useful",
"//:event_engine_base_hdrs",
"//:gpr",
],
)
grpc_cc_library( grpc_cc_library(
name = "ares_resolver", name = "ares_resolver",
srcs = [ srcs = [
"lib/event_engine/ares_resolver.cc", "lib/event_engine/ares_resolver.cc",
"lib/event_engine/windows/grpc_polled_fd_windows.cc",
], ],
hdrs = [ hdrs = [
"lib/event_engine/ares_resolver.h", "lib/event_engine/ares_resolver.h",
"lib/event_engine/grpc_polled_fd.h", "lib/event_engine/grpc_polled_fd.h",
"lib/event_engine/nameser.h", "lib/event_engine/nameser.h",
"lib/event_engine/posix_engine/grpc_polled_fd_posix.h", "lib/event_engine/posix_engine/grpc_polled_fd_posix.h",
"lib/event_engine/windows/grpc_polled_fd_windows.h",
], ],
external_deps = [ external_deps = [
"absl/base:core_headers", "absl/base:core_headers",
@ -2405,6 +2534,7 @@ grpc_cc_library(
"cares", "cares",
], ],
deps = [ deps = [
"common_event_engine_closures",
"error", "error",
"event_engine_time_util", "event_engine_time_util",
"grpc_sockaddr", "grpc_sockaddr",
@ -2412,7 +2542,10 @@ grpc_cc_library(
"posix_event_engine_closure", "posix_event_engine_closure",
"posix_event_engine_event_poller", "posix_event_engine_event_poller",
"posix_event_engine_tcp_socket_utils", "posix_event_engine_tcp_socket_utils",
"ref_counted_dns_resolver_interface",
"resolved_address", "resolved_address",
"slice",
"windows_iocp",
"//:debug_location", "//:debug_location",
"//:event_engine_base_hdrs", "//:event_engine_base_hdrs",
"//:gpr", "//:gpr",
@ -3082,15 +3215,23 @@ grpc_cc_library(
"lib/security/credentials/tls/grpc_tls_crl_provider.h", "lib/security/credentials/tls/grpc_tls_crl_provider.h",
], ],
external_deps = [ external_deps = [
"absl/base:core_headers",
"absl/container:flat_hash_map", "absl/container:flat_hash_map",
"absl/status", "absl/status",
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
"absl/types:optional",
"absl/types:span", "absl/types:span",
"libcrypto", "libcrypto",
"libssl", "libssl",
], ],
deps = [ deps = [
"default_event_engine",
"directory_reader",
"load_file",
"slice",
"time",
"//:exec_ctx",
"//:gpr", "//:gpr",
"//:grpc_base", "//:grpc_base",
], ],
@ -4047,13 +4188,16 @@ grpc_cc_library(
external_deps = [ external_deps = [
"absl/base:core_headers", "absl/base:core_headers",
"absl/container:inlined_vector", "absl/container:inlined_vector",
"absl/functional:function_ref",
"absl/status", "absl/status",
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
"absl/strings:str_format", "absl/strings:str_format",
"absl/types:optional", "absl/types:optional",
"absl/types:variant", "absl/types:variant",
"upb_base_lib",
"upb_lib", "upb_lib",
"upb_mem_lib",
], ],
language = "c++", language = "c++",
deps = [ deps = [
@ -4158,6 +4302,7 @@ grpc_cc_library(
"absl/strings", "absl/strings",
"absl/strings:str_format", "absl/strings:str_format",
"absl/types:optional", "absl/types:optional",
"upb_base_lib",
"upb_lib", "upb_lib",
], ],
language = "c++", language = "c++",
@ -4209,7 +4354,7 @@ grpc_cc_library(
], ],
external_deps = [ external_deps = [
"absl/strings", "absl/strings",
"upb_lib", "upb_base_lib",
], ],
language = "c++", language = "c++",
deps = ["//:gpr_platform"], deps = ["//:gpr_platform"],
@ -4284,7 +4429,9 @@ grpc_cc_library(
"absl/types:optional", "absl/types:optional",
"absl/types:span", "absl/types:span",
"absl/types:variant", "absl/types:variant",
"upb_base_lib",
"upb_lib", "upb_lib",
"upb_mem_lib",
"upb_textformat_lib", "upb_textformat_lib",
"upb_json_lib", "upb_json_lib",
"re2", "re2",
@ -4569,6 +4716,7 @@ grpc_cc_library(
"ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc", "ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc",
], ],
external_deps = [ external_deps = [
"absl/functional:function_ref",
"absl/status", "absl/status",
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
@ -4591,6 +4739,7 @@ grpc_cc_library(
"no_destruct", "no_destruct",
"pollset_set", "pollset_set",
"ref_counted_string", "ref_counted_string",
"resolved_address",
"validation_errors", "validation_errors",
"//:channel_arg_names", "//:channel_arg_names",
"//:config", "//:config",
@ -4739,6 +4888,7 @@ grpc_cc_library(
"ext/filters/client_channel/lb_policy/address_filtering.h", "ext/filters/client_channel/lb_policy/address_filtering.h",
], ],
external_deps = [ external_deps = [
"absl/functional:function_ref",
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
], ],
@ -4747,6 +4897,7 @@ grpc_cc_library(
"channel_args", "channel_args",
"ref_counted", "ref_counted",
"ref_counted_string", "ref_counted_string",
"resolved_address",
"//:endpoint_addresses", "//:endpoint_addresses",
"//:gpr_platform", "//:gpr_platform",
"//:ref_counted_ptr", "//:ref_counted_ptr",
@ -4768,6 +4919,7 @@ grpc_cc_library(
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
"absl/types:optional", "absl/types:optional",
"upb_base_lib",
"upb_lib", "upb_lib",
], ],
language = "c++", language = "c++",
@ -4815,6 +4967,7 @@ grpc_cc_library(
"lb_policy", "lb_policy",
"subchannel_interface", "subchannel_interface",
"//:debug_location", "//:debug_location",
"//:endpoint_addresses",
"//:gpr", "//:gpr",
"//:grpc_base", "//:grpc_base",
"//:ref_counted_ptr", "//:ref_counted_ptr",
@ -4832,7 +4985,7 @@ grpc_cc_library(
"ext/filters/client_channel/lb_policy/endpoint_list.h", "ext/filters/client_channel/lb_policy/endpoint_list.h",
], ],
external_deps = [ external_deps = [
"absl/functional:any_invocable", "absl/functional:function_ref",
"absl/status", "absl/status",
"absl/status:statusor", "absl/status:statusor",
"absl/types:optional", "absl/types:optional",
@ -5226,6 +5379,7 @@ grpc_cc_library(
], ],
external_deps = [ external_deps = [
"absl/base:core_headers", "absl/base:core_headers",
"absl/functional:function_ref",
"absl/status", "absl/status",
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
@ -5327,6 +5481,7 @@ grpc_cc_library(
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
"absl/types:optional", "absl/types:optional",
"upb_base_lib",
"upb_lib", "upb_lib",
], ],
language = "c++", language = "c++",
@ -5388,8 +5543,12 @@ grpc_cc_library(
grpc_cc_library( grpc_cc_library(
name = "service_config_helper", name = "service_config_helper",
srcs = ["ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc"], srcs = [
hdrs = ["ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h"], "ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc",
],
hdrs = [
"ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h",
],
external_deps = [ external_deps = [
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
@ -5409,8 +5568,12 @@ grpc_cc_library(
grpc_cc_library( grpc_cc_library(
name = "grpc_resolver_dns_event_engine", name = "grpc_resolver_dns_event_engine",
srcs = ["ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc"], srcs = [
hdrs = ["ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h"], "ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc",
],
hdrs = [
"ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h",
],
external_deps = [ external_deps = [
"absl/base:core_headers", "absl/base:core_headers",
"absl/cleanup", "absl/cleanup",
@ -5675,7 +5838,6 @@ grpc_cc_library(
hdrs = [ hdrs = [
"ext/transport/chttp2/transport/hpack_encoder_table.h", "ext/transport/chttp2/transport/hpack_encoder_table.h",
], ],
external_deps = ["absl/container:inlined_vector"],
language = "c++", language = "c++",
deps = [ deps = [
"hpack_constants", "hpack_constants",
@ -6021,6 +6183,7 @@ grpc_cc_library(
"arena", "arena",
"bitset", "bitset",
"chaotic_good_frame_header", "chaotic_good_frame_header",
"context",
"no_destruct", "no_destruct",
"slice", "slice",
"slice_buffer", "slice_buffer",
@ -6183,29 +6346,43 @@ grpc_cc_library(
], ],
external_deps = [ external_deps = [
"absl/base:core_headers", "absl/base:core_headers",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status", "absl/status",
"absl/status:statusor",
"absl/types:optional",
"absl/types:variant", "absl/types:variant",
], ],
language = "c++", language = "c++",
deps = [ deps = [
"activity", "activity",
"arena",
"chaotic_good_frame", "chaotic_good_frame",
"chaotic_good_frame_header", "chaotic_good_frame_header",
"context",
"event_engine_wakeup_scheduler", "event_engine_wakeup_scheduler",
"for_each", "for_each",
"grpc_promise_endpoint", "grpc_promise_endpoint",
"join", "if",
"inter_activity_pipe",
"loop", "loop",
"match", "match",
"memory_quota",
"mpsc", "mpsc",
"pipe", "pipe",
"seq", "poll",
"resource_quota",
"slice", "slice",
"slice_buffer", "slice_buffer",
"try_join",
"try_seq",
"//:exec_ctx",
"//:gpr", "//:gpr",
"//:gpr_platform", "//:gpr_platform",
"//:grpc_base", "//:grpc_base",
"//:hpack_encoder", "//:hpack_encoder",
"//:hpack_parser",
"//:ref_counted_ptr",
], ],
) )
@ -6338,7 +6515,9 @@ grpc_upb_proto_library(
grpc_upb_proto_library( grpc_upb_proto_library(
name = "envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_upb", name = "envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_upb",
deps = ["@envoy_api//envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3:pkg"], deps = [
"@envoy_api//envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3:pkg",
],
) )
grpc_upb_proto_library( grpc_upb_proto_library(
@ -6358,12 +6537,16 @@ grpc_upb_proto_library(
grpc_upb_proto_library( grpc_upb_proto_library(
name = "envoy_extensions_filters_network_http_connection_manager_upb", name = "envoy_extensions_filters_network_http_connection_manager_upb",
deps = ["@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg"], deps = [
"@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg",
],
) )
grpc_upb_proto_reflection_library( grpc_upb_proto_reflection_library(
name = "envoy_extensions_filters_network_http_connection_manager_upbdefs", name = "envoy_extensions_filters_network_http_connection_manager_upbdefs",
deps = ["@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg"], deps = [
"@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg",
],
) )
grpc_upb_proto_library( grpc_upb_proto_library(
@ -6490,14 +6673,20 @@ WELL_KNOWN_PROTO_TARGETS = [
"wrappers", "wrappers",
] ]
[grpc_upb_proto_library( [
name = "protobuf_" + target + "_upb", grpc_upb_proto_library(
deps = ["@com_google_protobuf//:" + target + "_proto"], name = "protobuf_" + target + "_upb",
) for target in WELL_KNOWN_PROTO_TARGETS] deps = ["@com_google_protobuf//:" + target + "_proto"],
)
for target in WELL_KNOWN_PROTO_TARGETS
]
[grpc_upb_proto_reflection_library( [
name = "protobuf_" + target + "_upbdefs", grpc_upb_proto_reflection_library(
deps = ["@com_google_protobuf//:" + target + "_proto"], name = "protobuf_" + target + "_upbdefs",
) for target in WELL_KNOWN_PROTO_TARGETS] deps = ["@com_google_protobuf//:" + target + "_proto"],
)
for target in WELL_KNOWN_PROTO_TARGETS
]
grpc_generate_one_off_internal_targets() grpc_generate_one_off_internal_targets()

@ -315,6 +315,14 @@ class ClientChannel::PromiseBasedCallData : public ClientChannel::CallData {
public: public:
explicit PromiseBasedCallData(ClientChannel* chand) : chand_(chand) {} explicit PromiseBasedCallData(ClientChannel* chand) : chand_(chand) {}
~PromiseBasedCallData() override {
if (was_queued_ && client_initial_metadata_ != nullptr) {
MutexLock lock(&chand_->resolution_mu_);
RemoveCallFromResolverQueuedCallsLocked();
chand_->resolver_queued_calls_.erase(this);
}
}
ArenaPromise<absl::StatusOr<CallArgs>> MakeNameResolutionPromise( ArenaPromise<absl::StatusOr<CallArgs>> MakeNameResolutionPromise(
CallArgs call_args) { CallArgs call_args) {
pollent_ = NowOrNever(call_args.polling_entity->WaitAndCopy()).value(); pollent_ = NowOrNever(call_args.polling_entity->WaitAndCopy()).value();
@ -399,6 +407,7 @@ class ClientChannel::PromiseBasedCallData : public ClientChannel::CallData {
const grpc_channel_filter ClientChannel::kFilterVtableWithPromises = { const grpc_channel_filter ClientChannel::kFilterVtableWithPromises = {
ClientChannel::FilterBasedCallData::StartTransportStreamOpBatch, ClientChannel::FilterBasedCallData::StartTransportStreamOpBatch,
ClientChannel::MakeCallPromise, ClientChannel::MakeCallPromise,
/* init_call: */ nullptr,
ClientChannel::StartTransportOp, ClientChannel::StartTransportOp,
sizeof(ClientChannel::FilterBasedCallData), sizeof(ClientChannel::FilterBasedCallData),
ClientChannel::FilterBasedCallData::Init, ClientChannel::FilterBasedCallData::Init,
@ -415,6 +424,7 @@ const grpc_channel_filter ClientChannel::kFilterVtableWithPromises = {
const grpc_channel_filter ClientChannel::kFilterVtableWithoutPromises = { const grpc_channel_filter ClientChannel::kFilterVtableWithoutPromises = {
ClientChannel::FilterBasedCallData::StartTransportStreamOpBatch, ClientChannel::FilterBasedCallData::StartTransportStreamOpBatch,
nullptr, nullptr,
/* init_call: */ nullptr,
ClientChannel::StartTransportOp, ClientChannel::StartTransportOp,
sizeof(ClientChannel::FilterBasedCallData), sizeof(ClientChannel::FilterBasedCallData),
ClientChannel::FilterBasedCallData::Init, ClientChannel::FilterBasedCallData::Init,
@ -562,6 +572,7 @@ class DynamicTerminationFilter::CallData {
const grpc_channel_filter DynamicTerminationFilter::kFilterVtable = { const grpc_channel_filter DynamicTerminationFilter::kFilterVtable = {
DynamicTerminationFilter::CallData::StartTransportStreamOpBatch, DynamicTerminationFilter::CallData::StartTransportStreamOpBatch,
DynamicTerminationFilter::MakeCallPromise, DynamicTerminationFilter::MakeCallPromise,
/* init_call: */ nullptr,
DynamicTerminationFilter::StartTransportOp, DynamicTerminationFilter::StartTransportOp,
sizeof(DynamicTerminationFilter::CallData), sizeof(DynamicTerminationFilter::CallData),
DynamicTerminationFilter::CallData::Init, DynamicTerminationFilter::CallData::Init,
@ -1599,7 +1610,12 @@ absl::Status ClientChannel::CreateOrUpdateLbPolicyLocked(
Resolver::Result result) { Resolver::Result result) {
// Construct update. // Construct update.
LoadBalancingPolicy::UpdateArgs update_args; LoadBalancingPolicy::UpdateArgs update_args;
update_args.addresses = std::move(result.addresses); if (!result.addresses.ok()) {
update_args.addresses = result.addresses.status();
} else {
update_args.addresses = std::make_shared<EndpointAddressesListIterator>(
std::move(*result.addresses));
}
update_args.config = std::move(lb_policy_config); update_args.config = std::move(lb_policy_config);
update_args.resolution_note = std::move(result.resolution_note); update_args.resolution_note = std::move(result.resolution_note);
// Remove the config selector from channel args so that we're not holding // Remove the config selector from channel args so that we're not holding

@ -20,11 +20,13 @@
#include <stddef.h> #include <stddef.h>
#include <algorithm>
#include <utility> #include <utility>
#include "absl/functional/function_ref.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/resolved_address.h"
namespace grpc_core { namespace grpc_core {
@ -43,32 +45,63 @@ int HierarchicalPathArg::ChannelArgsCompare(const HierarchicalPathArg* a,
return 0; return 0;
} }
namespace {
class HierarchicalAddressIterator : public EndpointAddressesIterator {
public:
HierarchicalAddressIterator(
std::shared_ptr<EndpointAddressesIterator> parent_it,
RefCountedStringValue child_name)
: parent_it_(std::move(parent_it)), child_name_(std::move(child_name)) {}
void ForEach(absl::FunctionRef<void(const EndpointAddresses&)> callback)
const override {
RefCountedPtr<HierarchicalPathArg> remaining_path_attr;
parent_it_->ForEach([&](const EndpointAddresses& endpoint) {
const auto* path_arg = endpoint.args().GetObject<HierarchicalPathArg>();
if (path_arg == nullptr) return;
const std::vector<RefCountedStringValue>& path = path_arg->path();
auto it = path.begin();
if (it == path.end()) return;
if (*it != child_name_) return;
ChannelArgs args = endpoint.args();
++it;
if (it != path.end()) {
std::vector<RefCountedStringValue> remaining_path(it, path.end());
if (remaining_path_attr == nullptr ||
remaining_path_attr->path() != remaining_path) {
remaining_path_attr =
MakeRefCounted<HierarchicalPathArg>(std::move(remaining_path));
}
args = args.SetObject(remaining_path_attr);
}
callback(EndpointAddresses(endpoint.addresses(), args));
});
}
private:
std::shared_ptr<EndpointAddressesIterator> parent_it_;
RefCountedStringValue child_name_;
};
} // namespace
absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap( absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap(
const absl::StatusOr<EndpointAddressesList>& addresses) { absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses) {
if (!addresses.ok()) return addresses.status(); if (!addresses.ok()) return addresses.status();
HierarchicalAddressMap result; HierarchicalAddressMap result;
RefCountedPtr<HierarchicalPathArg> remaining_path_attr; (*addresses)->ForEach([&](const EndpointAddresses& endpoint) {
for (const EndpointAddresses& endpoint_addresses : *addresses) { const auto* path_arg = endpoint.args().GetObject<HierarchicalPathArg>();
const auto* path_arg = if (path_arg == nullptr) return;
endpoint_addresses.args().GetObject<HierarchicalPathArg>();
if (path_arg == nullptr) continue;
const std::vector<RefCountedStringValue>& path = path_arg->path(); const std::vector<RefCountedStringValue>& path = path_arg->path();
auto it = path.begin(); auto it = path.begin();
if (it == path.end()) continue; if (it == path.end()) return;
EndpointAddressesList& target_list = result[*it]; auto& target_list = result[*it];
ChannelArgs args = endpoint_addresses.args(); if (target_list == nullptr) {
++it; target_list =
if (it != path.end()) { std::make_shared<HierarchicalAddressIterator>(*addresses, *it);
std::vector<RefCountedStringValue> remaining_path(it, path.end());
if (remaining_path_attr == nullptr ||
remaining_path_attr->path() != remaining_path) {
remaining_path_attr =
MakeRefCounted<HierarchicalPathArg>(std::move(remaining_path));
}
args = args.SetObject(remaining_path_attr);
} }
target_list.emplace_back(endpoint_addresses.addresses(), args); });
}
return result; return result;
} }

@ -20,6 +20,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <map> #include <map>
#include <memory>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -105,12 +106,12 @@ class HierarchicalPathArg : public RefCounted<HierarchicalPathArg> {
// A map from the next path element to the endpoint addresses that fall // A map from the next path element to the endpoint addresses that fall
// under that path element. // under that path element.
using HierarchicalAddressMap = using HierarchicalAddressMap =
std::map<RefCountedStringValue, EndpointAddressesList, std::map<RefCountedStringValue, std::shared_ptr<EndpointAddressesIterator>,
RefCountedStringValueLessThan>; RefCountedStringValueLessThan>;
// Splits up the addresses into a separate list for each child. // Splits up the addresses into a separate list for each child.
absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap( absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap(
const absl::StatusOr<EndpointAddressesList>& addresses); absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses);
} // namespace grpc_core } // namespace grpc_core

@ -98,7 +98,7 @@ class ChildPolicyHandler::Helper
: parent()->child_policy_.get(); : parent()->child_policy_.get();
if (child_ != latest_child_policy) return; if (child_ != latest_child_policy) return;
if (GRPC_TRACE_FLAG_ENABLED(*(parent()->tracer_))) { if (GRPC_TRACE_FLAG_ENABLED(*(parent()->tracer_))) {
gpr_log(GPR_INFO, "[child_policy_handler %p] started name re-resolving", gpr_log(GPR_INFO, "[child_policy_handler %p] requesting re-resolution",
parent()); parent());
} }
parent()->channel_control_helper()->RequestReresolution(); parent()->channel_control_helper()->RequestReresolution();

@ -118,7 +118,7 @@ void EndpointList::Endpoint::Init(
GPR_ASSERT(config.ok()); GPR_ASSERT(config.ok());
// Update child policy. // Update child policy.
LoadBalancingPolicy::UpdateArgs update_args; LoadBalancingPolicy::UpdateArgs update_args;
update_args.addresses.emplace().emplace_back(addresses); update_args.addresses = std::make_shared<SingleEndpointIterator>(addresses);
update_args.args = child_args; update_args.args = child_args;
update_args.config = std::move(*config); update_args.config = std::move(*config);
// TODO(roth): If the child reports a non-OK status with the update, // TODO(roth): If the child reports a non-OK status with the update,
@ -163,15 +163,16 @@ RefCountedPtr<SubchannelInterface> EndpointList::Endpoint::CreateSubchannel(
// //
void EndpointList::Init( void EndpointList::Init(
const EndpointAddressesList& endpoints, const ChannelArgs& args, EndpointAddressesIterator* endpoints, const ChannelArgs& args,
absl::AnyInvocable<OrphanablePtr<Endpoint>(RefCountedPtr<EndpointList>, absl::FunctionRef<OrphanablePtr<Endpoint>(RefCountedPtr<EndpointList>,
const EndpointAddresses&, const EndpointAddresses&,
const ChannelArgs&)> const ChannelArgs&)>
create_endpoint) { create_endpoint) {
for (const EndpointAddresses& addresses : endpoints) { if (endpoints == nullptr) return;
endpoints->ForEach([&](const EndpointAddresses& endpoint) {
endpoints_.push_back( endpoints_.push_back(
create_endpoint(Ref(DEBUG_LOCATION, "Endpoint"), addresses, args)); create_endpoint(Ref(DEBUG_LOCATION, "Endpoint"), endpoint, args));
} });
} }
void EndpointList::ResetBackoffLocked() { void EndpointList::ResetBackoffLocked() {

@ -25,7 +25,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "absl/functional/any_invocable.h" #include "absl/functional/function_ref.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
@ -53,7 +53,7 @@ namespace grpc_core {
class MyEndpointList : public EndpointList { class MyEndpointList : public EndpointList {
public: public:
MyEndpointList(RefCountedPtr<MyLbPolicy> lb_policy, MyEndpointList(RefCountedPtr<MyLbPolicy> lb_policy,
const EndpointAddressesList& endpoints, EndpointAddressesIterator* endpoints,
const ChannelArgs& args) const ChannelArgs& args)
: EndpointList(std::move(lb_policy), : EndpointList(std::move(lb_policy),
GRPC_TRACE_FLAG_ENABLED(grpc_my_tracer) GRPC_TRACE_FLAG_ENABLED(grpc_my_tracer)
@ -184,8 +184,8 @@ class EndpointList : public InternallyRefCounted<EndpointList> {
EndpointList(RefCountedPtr<LoadBalancingPolicy> policy, const char* tracer) EndpointList(RefCountedPtr<LoadBalancingPolicy> policy, const char* tracer)
: policy_(std::move(policy)), tracer_(tracer) {} : policy_(std::move(policy)), tracer_(tracer) {}
void Init(const EndpointAddressesList& endpoints, const ChannelArgs& args, void Init(EndpointAddressesIterator* endpoints, const ChannelArgs& args,
absl::AnyInvocable<OrphanablePtr<Endpoint>( absl::FunctionRef<OrphanablePtr<Endpoint>(
RefCountedPtr<EndpointList>, const EndpointAddresses&, RefCountedPtr<EndpointList>, const EndpointAddresses&,
const ChannelArgs&)> const ChannelArgs&)>
create_endpoint); create_endpoint);

@ -72,6 +72,7 @@
#include <vector> #include <vector>
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
#include "absl/functional/function_ref.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
@ -384,9 +385,9 @@ class GrpcLb : public LoadBalancingPolicy {
// Returns a text representation suitable for logging. // Returns a text representation suitable for logging.
std::string AsText() const; std::string AsText() const;
// Extracts all non-drop entries into an EndpointAddressesList. // Extracts all non-drop entries into an EndpointAddressesIterator.
EndpointAddressesList GetServerAddressList( std::shared_ptr<EndpointAddressesIterator> GetServerAddressList(
GrpcLbClientStats* client_stats) const; GrpcLbClientStats* client_stats);
// Returns true if the serverlist contains at least one drop entry and // Returns true if the serverlist contains at least one drop entry and
// no backend address entries. // no backend address entries.
@ -400,6 +401,8 @@ class GrpcLb : public LoadBalancingPolicy {
const char* ShouldDrop(); const char* ShouldDrop();
private: private:
class AddressIterator;
std::vector<GrpcLbServer> serverlist_; std::vector<GrpcLbServer> serverlist_;
// Accessed from the picker, so needs synchronization. // Accessed from the picker, so needs synchronization.
@ -504,6 +507,8 @@ class GrpcLb : public LoadBalancingPolicy {
RefCountedPtr<GrpcLb> parent_; RefCountedPtr<GrpcLb> parent_;
}; };
class NullLbTokenEndpointIterator;
void ShutdownLocked() override; void ShutdownLocked() override;
// Helper functions used in UpdateLocked(). // Helper functions used in UpdateLocked().
@ -569,7 +574,8 @@ class GrpcLb : public LoadBalancingPolicy {
// Whether we're in fallback mode. // Whether we're in fallback mode.
bool fallback_mode_ = false; bool fallback_mode_ = false;
// The backend addresses from the resolver. // The backend addresses from the resolver.
absl::StatusOr<EndpointAddressesList> fallback_backend_addresses_; absl::StatusOr<std::shared_ptr<NullLbTokenEndpointIterator>>
fallback_backend_addresses_;
// The last resolution note from our parent. // The last resolution note from our parent.
// To be passed to child policy when fallback_backend_addresses_ is empty. // To be passed to child policy when fallback_backend_addresses_ is empty.
std::string resolution_note_; std::string resolution_note_;
@ -594,11 +600,30 @@ class GrpcLb : public LoadBalancingPolicy {
}; };
// //
// GrpcLb::Serverlist // GrpcLb::Serverlist::AddressIterator
// //
bool GrpcLb::Serverlist::operator==(const Serverlist& other) const { bool IsServerValid(const GrpcLbServer& server, size_t idx, bool log) {
return serverlist_ == other.serverlist_; if (server.drop) return false;
if (GPR_UNLIKELY(server.port >> 16 != 0)) {
if (log) {
gpr_log(GPR_ERROR,
"Invalid port '%d' at index %" PRIuPTR
" of serverlist. Ignoring.",
server.port, idx);
}
return false;
}
if (GPR_UNLIKELY(server.ip_size != 4 && server.ip_size != 16)) {
if (log) {
gpr_log(GPR_ERROR,
"Expected IP to be 4 or 16 bytes, got %d at index %" PRIuPTR
" of serverlist. Ignoring",
server.ip_size, idx);
}
return false;
}
return true;
} }
void ParseServer(const GrpcLbServer& server, grpc_resolved_address* addr) { void ParseServer(const GrpcLbServer& server, grpc_resolved_address* addr) {
@ -623,6 +648,53 @@ void ParseServer(const GrpcLbServer& server, grpc_resolved_address* addr) {
} }
} }
class GrpcLb::Serverlist::AddressIterator : public EndpointAddressesIterator {
public:
AddressIterator(RefCountedPtr<Serverlist> serverlist,
RefCountedPtr<GrpcLbClientStats> client_stats)
: serverlist_(std::move(serverlist)),
client_stats_(std::move(client_stats)) {}
void ForEach(absl::FunctionRef<void(const EndpointAddresses&)> callback)
const override {
for (size_t i = 0; i < serverlist_->serverlist_.size(); ++i) {
const GrpcLbServer& server = serverlist_->serverlist_[i];
if (!IsServerValid(server, i, false)) continue;
// Address processing.
grpc_resolved_address addr;
ParseServer(server, &addr);
// LB token processing.
const size_t lb_token_length = strnlen(
server.load_balance_token, GPR_ARRAY_SIZE(server.load_balance_token));
std::string lb_token(server.load_balance_token, lb_token_length);
if (lb_token.empty()) {
auto addr_uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO,
"Missing LB token for backend address '%s'. The empty token "
"will be used instead",
addr_uri.ok() ? addr_uri->c_str()
: addr_uri.status().ToString().c_str());
}
// Return address with a channel arg containing LB token and stats object.
callback(EndpointAddresses(
addr, ChannelArgs().SetObject(MakeRefCounted<TokenAndClientStatsArg>(
std::move(lb_token), client_stats_))));
}
}
private:
RefCountedPtr<Serverlist> serverlist_;
RefCountedPtr<GrpcLbClientStats> client_stats_;
};
//
// GrpcLb::Serverlist
//
bool GrpcLb::Serverlist::operator==(const Serverlist& other) const {
return serverlist_ == other.serverlist_;
}
std::string GrpcLb::Serverlist::AsText() const { std::string GrpcLb::Serverlist::AsText() const {
std::vector<std::string> entries; std::vector<std::string> entries;
for (size_t i = 0; i < serverlist_.size(); ++i) { for (size_t i = 0; i < serverlist_.size(); ++i) {
@ -642,59 +714,12 @@ std::string GrpcLb::Serverlist::AsText() const {
return absl::StrJoin(entries, ""); return absl::StrJoin(entries, "");
} }
bool IsServerValid(const GrpcLbServer& server, size_t idx, bool log) {
if (server.drop) return false;
if (GPR_UNLIKELY(server.port >> 16 != 0)) {
if (log) {
gpr_log(GPR_ERROR,
"Invalid port '%d' at index %" PRIuPTR
" of serverlist. Ignoring.",
server.port, idx);
}
return false;
}
if (GPR_UNLIKELY(server.ip_size != 4 && server.ip_size != 16)) {
if (log) {
gpr_log(GPR_ERROR,
"Expected IP to be 4 or 16 bytes, got %d at index %" PRIuPTR
" of serverlist. Ignoring",
server.ip_size, idx);
}
return false;
}
return true;
}
// Returns addresses extracted from the serverlist. // Returns addresses extracted from the serverlist.
EndpointAddressesList GrpcLb::Serverlist::GetServerAddressList( std::shared_ptr<EndpointAddressesIterator>
GrpcLbClientStats* client_stats) const { GrpcLb::Serverlist::GetServerAddressList(GrpcLbClientStats* client_stats) {
RefCountedPtr<GrpcLbClientStats> stats; RefCountedPtr<GrpcLbClientStats> stats;
if (client_stats != nullptr) stats = client_stats->Ref(); if (client_stats != nullptr) stats = client_stats->Ref();
EndpointAddressesList endpoints; return std::make_shared<AddressIterator>(Ref(), std::move(stats));
for (size_t i = 0; i < serverlist_.size(); ++i) {
const GrpcLbServer& server = serverlist_[i];
if (!IsServerValid(server, i, false)) continue;
// Address processing.
grpc_resolved_address addr;
ParseServer(server, &addr);
// LB token processing.
const size_t lb_token_length = strnlen(
server.load_balance_token, GPR_ARRAY_SIZE(server.load_balance_token));
std::string lb_token(server.load_balance_token, lb_token_length);
if (lb_token.empty()) {
auto addr_uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO,
"Missing LB token for backend address '%s'. The empty token will "
"be used instead",
addr_uri.ok() ? addr_uri->c_str()
: addr_uri.status().ToString().c_str());
}
// Add address with a channel arg containing LB token and stats object.
endpoints.emplace_back(
addr, ChannelArgs().SetObject(MakeRefCounted<TokenAndClientStatsArg>(
std::move(lb_token), stats)));
}
return endpoints;
} }
bool GrpcLb::Serverlist::ContainsAllDropEntries() const { bool GrpcLb::Serverlist::ContainsAllDropEntries() const {
@ -841,14 +866,10 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
void GrpcLb::Helper::RequestReresolution() { void GrpcLb::Helper::RequestReresolution() {
if (parent()->shutting_down_) return; if (parent()->shutting_down_) return;
// If we are talking to a balancer, we expect to get updated addresses // Ignore if we're not in fallback mode, because if we got the backend
// from the balancer, so we can ignore the re-resolution request from // addresses from the balancer, re-resolving is not going to fix it.
// the child policy. Otherwise, pass the re-resolution request up to the if (!parent()->fallback_mode_) return;
// channel. parent()->channel_control_helper()->RequestReresolution();
if (parent()->lb_calld_ == nullptr ||
!parent()->lb_calld_->seen_initial_response()) {
parent()->channel_control_helper()->RequestReresolution();
}
} }
// //
@ -1507,21 +1528,45 @@ void GrpcLb::ResetBackoffLocked() {
} }
} }
// Endpoint iterator wrapper to add null LB token attribute.
class GrpcLb::NullLbTokenEndpointIterator : public EndpointAddressesIterator {
public:
explicit NullLbTokenEndpointIterator(
std::shared_ptr<EndpointAddressesIterator> parent_it)
: parent_it_(std::move(parent_it)) {}
void ForEach(absl::FunctionRef<void(const EndpointAddresses&)> callback)
const override {
parent_it_->ForEach([&](const EndpointAddresses& endpoint) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO, "[grpclb %p] fallback address: %s", this,
endpoint.ToString().c_str());
}
callback(EndpointAddresses(endpoint.addresses(),
endpoint.args().SetObject(empty_token_)));
});
}
private:
std::shared_ptr<EndpointAddressesIterator> parent_it_;
RefCountedPtr<TokenAndClientStatsArg> empty_token_ =
MakeRefCounted<TokenAndClientStatsArg>("", nullptr);
};
absl::Status GrpcLb::UpdateLocked(UpdateArgs args) { absl::Status GrpcLb::UpdateLocked(UpdateArgs args) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO, "[grpclb %p] received update", this);
}
const bool is_initial_update = lb_channel_ == nullptr; const bool is_initial_update = lb_channel_ == nullptr;
config_ = args.config; config_ = args.config;
GPR_ASSERT(config_ != nullptr); GPR_ASSERT(config_ != nullptr);
args_ = std::move(args.args); args_ = std::move(args.args);
// Update fallback address list. // Update fallback address list.
fallback_backend_addresses_ = std::move(args.addresses); if (!args.addresses.ok()) {
if (fallback_backend_addresses_.ok()) { fallback_backend_addresses_ = args.addresses.status();
// Add null LB token attributes. } else {
for (EndpointAddresses& addresses : *fallback_backend_addresses_) { fallback_backend_addresses_ = std::make_shared<NullLbTokenEndpointIterator>(
addresses = EndpointAddresses( std::move(*args.addresses));
addresses.addresses(),
addresses.args().SetObject(
MakeRefCounted<TokenAndClientStatsArg>("", nullptr)));
}
} }
resolution_note_ = std::move(args.resolution_note); resolution_note_ = std::move(args.resolution_note);
// Update balancer channel. // Update balancer channel.
@ -1569,6 +1614,12 @@ absl::Status GrpcLb::UpdateLocked(UpdateArgs args) {
absl::Status GrpcLb::UpdateBalancerChannelLocked() { absl::Status GrpcLb::UpdateBalancerChannelLocked() {
// Get balancer addresses. // Get balancer addresses.
EndpointAddressesList balancer_addresses = ExtractBalancerAddresses(args_); EndpointAddressesList balancer_addresses = ExtractBalancerAddresses(args_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
for (const auto& endpoint : balancer_addresses) {
gpr_log(GPR_INFO, "[grpclb %p] balancer address: %s", this,
endpoint.ToString().c_str());
}
}
absl::Status status; absl::Status status;
if (balancer_addresses.empty()) { if (balancer_addresses.empty()) {
status = absl::UnavailableError("balancer address list must be non-empty"); status = absl::UnavailableError("balancer address list must be non-empty");
@ -1747,6 +1798,12 @@ OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
return lb_policy; return lb_policy;
} }
bool EndpointIteratorIsEmpty(const EndpointAddressesIterator& endpoints) {
bool empty = true;
endpoints.ForEach([&](const EndpointAddresses&) { empty = false; });
return empty;
}
void GrpcLb::CreateOrUpdateChildPolicyLocked() { void GrpcLb::CreateOrUpdateChildPolicyLocked() {
if (shutting_down_) return; if (shutting_down_) return;
// Construct update args. // Construct update args.
@ -1760,16 +1817,17 @@ void GrpcLb::CreateOrUpdateChildPolicyLocked() {
// picks. // picks.
update_args.addresses = fallback_backend_addresses_; update_args.addresses = fallback_backend_addresses_;
if (fallback_backend_addresses_.ok() && if (fallback_backend_addresses_.ok() &&
fallback_backend_addresses_->empty()) { EndpointIteratorIsEmpty(**fallback_backend_addresses_)) {
update_args.resolution_note = absl::StrCat( update_args.resolution_note = absl::StrCat(
"grpclb in fallback mode without any balancer addresses: ", "grpclb in fallback mode without any fallback addresses: ",
resolution_note_); resolution_note_);
} }
} else { } else {
update_args.addresses = serverlist_->GetServerAddressList( update_args.addresses = serverlist_->GetServerAddressList(
lb_calld_ == nullptr ? nullptr : lb_calld_->client_stats()); lb_calld_ == nullptr ? nullptr : lb_calld_->client_stats());
is_backend_from_grpclb_load_balancer = true; is_backend_from_grpclb_load_balancer = true;
if (update_args.addresses.ok() && update_args.addresses->empty()) { if (update_args.addresses.ok() &&
EndpointIteratorIsEmpty(**update_args.addresses)) {
update_args.resolution_note = "empty serverlist from grpclb balancer"; update_args.resolution_note = "empty serverlist from grpclb balancer";
} }
} }

@ -661,7 +661,7 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
if (args.addresses.ok()) { if (args.addresses.ok()) {
std::set<EndpointAddressSet> current_endpoints; std::set<EndpointAddressSet> current_endpoints;
std::set<grpc_resolved_address, ResolvedAddressLessThan> current_addresses; std::set<grpc_resolved_address, ResolvedAddressLessThan> current_addresses;
for (const EndpointAddresses& endpoint : *args.addresses) { (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
EndpointAddressSet key(endpoint.addresses()); EndpointAddressSet key(endpoint.addresses());
current_endpoints.emplace(key); current_endpoints.emplace(key);
for (const grpc_resolved_address& address : endpoint.addresses()) { for (const grpc_resolved_address& address : endpoint.addresses()) {
@ -708,7 +708,7 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
} }
it->second->DisableEjection(); it->second->DisableEjection();
} }
} });
// Remove any entries we no longer need in the subchannel map. // Remove any entries we no longer need in the subchannel map.
for (auto it = subchannel_state_map_.begin(); for (auto it = subchannel_state_map_.begin();
it != subchannel_state_map_.end();) { it != subchannel_state_map_.end();) {
@ -753,7 +753,6 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
update_args.addresses = std::move(args.addresses); update_args.addresses = std::move(args.addresses);
update_args.resolution_note = std::move(args.resolution_note); update_args.resolution_note = std::move(args.resolution_note);
update_args.config = config_->child_policy(); update_args.config = config_->child_policy();
// Update the policy.
update_args.args = std::move(args.args); update_args.args = std::move(args.args);
if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,

@ -21,7 +21,6 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <algorithm>
#include <memory> #include <memory>
#include <set> #include <set>
#include <string> #include <string>
@ -114,7 +113,7 @@ class PickFirst : public LoadBalancingPolicy {
public: public:
class SubchannelData { class SubchannelData {
public: public:
SubchannelData(SubchannelList* subchannel_list, SubchannelData(SubchannelList* subchannel_list, size_t index,
RefCountedPtr<SubchannelInterface> subchannel); RefCountedPtr<SubchannelInterface> subchannel);
SubchannelInterface* subchannel() const { return subchannel_.get(); } SubchannelInterface* subchannel() const { return subchannel_.get(); }
@ -125,12 +124,6 @@ class PickFirst : public LoadBalancingPolicy {
return connectivity_status_; return connectivity_status_;
} }
// Returns the index into the subchannel list of this object.
size_t Index() const {
return static_cast<size_t>(this -
&subchannel_list_->subchannels_.front());
}
// Resets the connection backoff. // Resets the connection backoff.
void ResetBackoffLocked() { void ResetBackoffLocked() {
if (subchannel_ != nullptr) subchannel_->ResetBackoff(); if (subchannel_ != nullptr) subchannel_->ResetBackoff();
@ -153,10 +146,8 @@ class PickFirst : public LoadBalancingPolicy {
class Watcher class Watcher
: public SubchannelInterface::ConnectivityStateWatcherInterface { : public SubchannelInterface::ConnectivityStateWatcherInterface {
public: public:
Watcher(SubchannelData* subchannel_data, Watcher(RefCountedPtr<SubchannelList> subchannel_list, size_t index)
RefCountedPtr<SubchannelList> subchannel_list) : subchannel_list_(std::move(subchannel_list)), index_(index) {}
: subchannel_data_(subchannel_data),
subchannel_list_(std::move(subchannel_list)) {}
~Watcher() override { ~Watcher() override {
subchannel_list_.reset(DEBUG_LOCATION, "Watcher dtor"); subchannel_list_.reset(DEBUG_LOCATION, "Watcher dtor");
@ -164,8 +155,8 @@ class PickFirst : public LoadBalancingPolicy {
void OnConnectivityStateChange(grpc_connectivity_state new_state, void OnConnectivityStateChange(grpc_connectivity_state new_state,
absl::Status status) override { absl::Status status) override {
subchannel_data_->OnConnectivityStateChange(new_state, subchannel_list_->subchannels_[index_].OnConnectivityStateChange(
std::move(status)); new_state, std::move(status));
} }
grpc_pollset_set* interested_parties() override { grpc_pollset_set* interested_parties() override {
@ -173,8 +164,8 @@ class PickFirst : public LoadBalancingPolicy {
} }
private: private:
SubchannelData* subchannel_data_;
RefCountedPtr<SubchannelList> subchannel_list_; RefCountedPtr<SubchannelList> subchannel_list_;
const size_t index_;
}; };
// This method will be invoked once soon after instantiation to report // This method will be invoked once soon after instantiation to report
@ -193,6 +184,7 @@ class PickFirst : public LoadBalancingPolicy {
// Backpointer to owning subchannel list. Not owned. // Backpointer to owning subchannel list. Not owned.
SubchannelList* subchannel_list_; SubchannelList* subchannel_list_;
const size_t index_;
// The subchannel. // The subchannel.
RefCountedPtr<SubchannelInterface> subchannel_; RefCountedPtr<SubchannelInterface> subchannel_;
// Will be non-null when the subchannel's state is being watched. // Will be non-null when the subchannel's state is being watched.
@ -205,7 +197,8 @@ class PickFirst : public LoadBalancingPolicy {
}; };
SubchannelList(RefCountedPtr<PickFirst> policy, SubchannelList(RefCountedPtr<PickFirst> policy,
EndpointAddressesList addresses, const ChannelArgs& args); EndpointAddressesIterator* addresses,
const ChannelArgs& args);
~SubchannelList() override; ~SubchannelList() override;
@ -321,6 +314,14 @@ class PickFirst : public LoadBalancingPolicy {
void UnsetSelectedSubchannel(); void UnsetSelectedSubchannel();
// When ExitIdleLocked() is called, we create a subchannel_list_ and start
// trying to connect, but we don't actually change state_ until the first
// subchannel reports CONNECTING. So in order to know if we're really
// idle, we need to check both state_ and subchannel_list_.
bool IsIdle() const {
return state_ == GRPC_CHANNEL_IDLE && subchannel_list_ == nullptr;
}
// Whether we should enable health watching. // Whether we should enable health watching.
const bool enable_health_watch_; const bool enable_health_watch_;
// Whether we should omit our status message prefix. // Whether we should omit our status message prefix.
@ -388,10 +389,7 @@ void PickFirst::ShutdownLocked() {
void PickFirst::ExitIdleLocked() { void PickFirst::ExitIdleLocked() {
if (shutdown_) return; if (shutdown_) return;
// Need to check subchannel_list_ being null here, in case the if (IsIdle()) {
// application calls channel->GetState(true) again before we
// transition to state CONNECTING.
if (state_ == GRPC_CHANNEL_IDLE && subchannel_list_ == nullptr) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO, "Pick First %p exiting idle", this); gpr_log(GPR_INFO, "Pick First %p exiting idle", this);
} }
@ -408,9 +406,9 @@ void PickFirst::ResetBackoffLocked() {
void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() { void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
// Create a subchannel list from latest_update_args_. // Create a subchannel list from latest_update_args_.
EndpointAddressesList addresses; EndpointAddressesIterator* addresses = nullptr;
if (latest_update_args_.addresses.ok()) { if (latest_update_args_.addresses.ok()) {
addresses = *latest_update_args_.addresses; addresses = latest_update_args_.addresses->get();
} }
// Replace latest_pending_subchannel_list_. // Replace latest_pending_subchannel_list_.
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace) && if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace) &&
@ -420,7 +418,7 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
latest_pending_subchannel_list_.get()); latest_pending_subchannel_list_.get());
} }
latest_pending_subchannel_list_ = MakeOrphanable<SubchannelList>( latest_pending_subchannel_list_ = MakeOrphanable<SubchannelList>(
Ref(), std::move(addresses), latest_update_args_.args); Ref(), addresses, latest_update_args_.args);
// Empty update or no valid subchannels. Put the channel in // Empty update or no valid subchannels. Put the channel in
// TRANSIENT_FAILURE and request re-resolution. // TRANSIENT_FAILURE and request re-resolution.
if (latest_pending_subchannel_list_->size() == 0) { if (latest_pending_subchannel_list_->size() == 0) {
@ -478,9 +476,7 @@ class AddressFamilyIterator {
absl::Status PickFirst::UpdateLocked(UpdateArgs args) { absl::Status PickFirst::UpdateLocked(UpdateArgs args) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
if (args.addresses.ok()) { if (args.addresses.ok()) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO, "Pick First %p received update", this);
"Pick First %p received update with %" PRIuPTR " addresses", this,
args.addresses->size());
} else { } else {
gpr_log(GPR_INFO, "Pick First %p received update with address error: %s", gpr_log(GPR_INFO, "Pick First %p received update with address error: %s",
this, args.addresses.status().ToString().c_str()); this, args.addresses.status().ToString().c_str());
@ -490,51 +486,59 @@ absl::Status PickFirst::UpdateLocked(UpdateArgs args) {
absl::Status status; absl::Status status;
if (!args.addresses.ok()) { if (!args.addresses.ok()) {
status = args.addresses.status(); status = args.addresses.status();
} else if (args.addresses->empty()) {
status = absl::UnavailableError("address list must not be empty");
} else { } else {
// Shuffle the list if needed.
auto config = static_cast<PickFirstConfig*>(args.config.get());
if (config->shuffle_addresses()) {
absl::c_shuffle(*args.addresses, bit_gen_);
}
// Flatten the list so that we have one address per endpoint.
// While we're iterating, also determine the desired address family
// order and the index of the first element of each family, for use in
// the interleaving below.
std::set<absl::string_view> address_families;
std::vector<AddressFamilyIterator> address_family_order;
EndpointAddressesList endpoints; EndpointAddressesList endpoints;
for (const auto& endpoint : *args.addresses) { (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
for (const auto& address : endpoint.addresses()) { endpoints.push_back(endpoint);
endpoints.emplace_back(address, endpoint.args()); });
if (IsPickFirstHappyEyeballsEnabled()) { if (endpoints.empty()) {
absl::string_view scheme = GetAddressFamily(address); status = absl::UnavailableError("address list must not be empty");
bool inserted = address_families.insert(scheme).second; } else {
if (inserted) { // Shuffle the list if needed.
address_family_order.emplace_back(scheme, endpoints.size() - 1); auto config = static_cast<PickFirstConfig*>(args.config.get());
if (config->shuffle_addresses()) {
absl::c_shuffle(endpoints, bit_gen_);
}
// Flatten the list so that we have one address per endpoint.
// While we're iterating, also determine the desired address family
// order and the index of the first element of each family, for use in
// the interleaving below.
std::set<absl::string_view> address_families;
std::vector<AddressFamilyIterator> address_family_order;
EndpointAddressesList flattened_endpoints;
for (const auto& endpoint : endpoints) {
for (const auto& address : endpoint.addresses()) {
flattened_endpoints.emplace_back(address, endpoint.args());
if (IsPickFirstHappyEyeballsEnabled()) {
absl::string_view scheme = GetAddressFamily(address);
bool inserted = address_families.insert(scheme).second;
if (inserted) {
address_family_order.emplace_back(scheme,
flattened_endpoints.size() - 1);
}
} }
} }
} }
} endpoints = std::move(flattened_endpoints);
// Interleave addresses as per RFC-8305 section 4. // Interleave addresses as per RFC-8305 section 4.
if (IsPickFirstHappyEyeballsEnabled()) { if (IsPickFirstHappyEyeballsEnabled()) {
EndpointAddressesList interleaved_endpoints; EndpointAddressesList interleaved_endpoints;
interleaved_endpoints.reserve(endpoints.size()); interleaved_endpoints.reserve(endpoints.size());
std::vector<bool> endpoints_moved(endpoints.size()); std::vector<bool> endpoints_moved(endpoints.size());
size_t scheme_index = 0; size_t scheme_index = 0;
for (size_t i = 0; i < endpoints.size(); ++i) { for (size_t i = 0; i < endpoints.size(); ++i) {
EndpointAddresses* endpoint; EndpointAddresses* endpoint;
do { do {
auto& iterator = address_family_order[scheme_index++ % auto& iterator = address_family_order[scheme_index++ %
address_family_order.size()]; address_family_order.size()];
endpoint = iterator.Next(endpoints, &endpoints_moved); endpoint = iterator.Next(endpoints, &endpoints_moved);
} while (endpoint == nullptr); } while (endpoint == nullptr);
interleaved_endpoints.emplace_back(std::move(*endpoint)); interleaved_endpoints.emplace_back(std::move(*endpoint));
}
endpoints = std::move(interleaved_endpoints);
} }
args.addresses = std::move(interleaved_endpoints); args.addresses =
} else { std::make_shared<EndpointAddressesListIterator>(std::move(endpoints));
args.addresses = std::move(endpoints);
} }
} }
// If the update contains a resolver error and we have a previous update // If the update contains a resolver error and we have a previous update
@ -546,7 +550,7 @@ absl::Status PickFirst::UpdateLocked(UpdateArgs args) {
latest_update_args_ = std::move(args); latest_update_args_ = std::move(args);
// If we are not in idle, start connection attempt immediately. // If we are not in idle, start connection attempt immediately.
// Otherwise, we defer the attempt into ExitIdleLocked(). // Otherwise, we defer the attempt into ExitIdleLocked().
if (state_ != GRPC_CHANNEL_IDLE) { if (!IsIdle()) {
AttemptToConnectUsingLatestUpdateArgsLocked(); AttemptToConnectUsingLatestUpdateArgsLocked();
} }
return status; return status;
@ -612,18 +616,20 @@ void PickFirst::HealthWatcher::OnConnectivityStateChange(
// //
PickFirst::SubchannelList::SubchannelData::SubchannelData( PickFirst::SubchannelList::SubchannelData::SubchannelData(
SubchannelList* subchannel_list, SubchannelList* subchannel_list, size_t index,
RefCountedPtr<SubchannelInterface> subchannel) RefCountedPtr<SubchannelInterface> subchannel)
: subchannel_list_(subchannel_list), subchannel_(std::move(subchannel)) { : subchannel_list_(subchannel_list),
index_(index),
subchannel_(std::move(subchannel)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[PF %p] subchannel list %p index %" PRIuPTR "[PF %p] subchannel list %p index %" PRIuPTR
" (subchannel %p): starting watch", " (subchannel %p): starting watch",
subchannel_list_->policy_.get(), subchannel_list_, subchannel_list_->policy_.get(), subchannel_list_, index_,
subchannel_list_->size(), subchannel_.get()); subchannel_.get());
} }
auto watcher = std::make_unique<Watcher>( auto watcher = std::make_unique<Watcher>(
this, subchannel_list_->Ref(DEBUG_LOCATION, "Watcher")); subchannel_list_->Ref(DEBUG_LOCATION, "Watcher"), index_);
pending_watcher_ = watcher.get(); pending_watcher_ = watcher.get();
subchannel_->WatchConnectivityState(std::move(watcher)); subchannel_->WatchConnectivityState(std::move(watcher));
} }
@ -634,7 +640,7 @@ void PickFirst::SubchannelList::SubchannelData::ShutdownLocked() {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[PF %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR "[PF %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
" (subchannel %p): cancelling watch and unreffing subchannel", " (subchannel %p): cancelling watch and unreffing subchannel",
subchannel_list_->policy_.get(), subchannel_list_, Index(), subchannel_list_->policy_.get(), subchannel_list_, index_,
subchannel_list_->size(), subchannel_.get()); subchannel_list_->size(), subchannel_.get());
} }
subchannel_->CancelConnectivityStateWatch(pending_watcher_); subchannel_->CancelConnectivityStateWatch(pending_watcher_);
@ -654,7 +660,7 @@ void PickFirst::SubchannelList::SubchannelData::OnConnectivityStateChange(
"status=%s, shutting_down=%d, pending_watcher=%p, " "status=%s, shutting_down=%d, pending_watcher=%p, "
"seen_transient_failure=%d, p->selected_=%p, " "seen_transient_failure=%d, p->selected_=%p, "
"p->subchannel_list_=%p, p->latest_pending_subchannel_list_=%p", "p->subchannel_list_=%p, p->latest_pending_subchannel_list_=%p",
p, subchannel_list_, Index(), subchannel_list_->size(), p, subchannel_list_, index_, subchannel_list_->size(),
subchannel_.get(), subchannel_.get(),
(connectivity_state_.has_value() (connectivity_state_.has_value()
? ConnectivityStateName(*connectivity_state_) ? ConnectivityStateName(*connectivity_state_)
@ -766,7 +772,7 @@ void PickFirst::SubchannelList::SubchannelData::OnConnectivityStateChange(
if (!IsPickFirstHappyEyeballsEnabled()) { if (!IsPickFirstHappyEyeballsEnabled()) {
// Ignore any other updates for subchannels we're not currently trying to // Ignore any other updates for subchannels we're not currently trying to
// connect to. // connect to.
if (Index() != subchannel_list_->attempting_index_) return; if (index_ != subchannel_list_->attempting_index_) return;
// React to the connectivity state. // React to the connectivity state.
ReactToConnectivityStateLocked(); ReactToConnectivityStateLocked();
return; return;
@ -779,7 +785,7 @@ void PickFirst::SubchannelList::SubchannelData::OnConnectivityStateChange(
if (!prev_seen_transient_failure && seen_transient_failure_) { if (!prev_seen_transient_failure && seen_transient_failure_) {
// If a connection attempt fails before the timer fires, then // If a connection attempt fails before the timer fires, then
// cancel the timer and start connecting on the next subchannel. // cancel the timer and start connecting on the next subchannel.
if (Index() == subchannel_list_->attempting_index_) { if (index_ == subchannel_list_->attempting_index_) {
if (subchannel_list_->timer_handle_.has_value()) { if (subchannel_list_->timer_handle_.has_value()) {
p->channel_control_helper()->GetEventEngine()->Cancel( p->channel_control_helper()->GetEventEngine()->Cancel(
*subchannel_list_->timer_handle_); *subchannel_list_->timer_handle_);
@ -853,7 +859,7 @@ void PickFirst::SubchannelList::SubchannelData::
// We skip subchannels in state TRANSIENT_FAILURE to avoid a // We skip subchannels in state TRANSIENT_FAILURE to avoid a
// large recursion that could overflow the stack. // large recursion that could overflow the stack.
SubchannelData* found_subchannel = nullptr; SubchannelData* found_subchannel = nullptr;
for (size_t next_index = Index() + 1; for (size_t next_index = index_ + 1;
next_index < subchannel_list_->size(); ++next_index) { next_index < subchannel_list_->size(); ++next_index) {
SubchannelData* sc = &subchannel_list_->subchannels_[next_index]; SubchannelData* sc = &subchannel_list_->subchannels_[next_index];
GPR_ASSERT(sc->connectivity_state_.has_value()); GPR_ASSERT(sc->connectivity_state_.has_value());
@ -941,14 +947,14 @@ void PickFirst::SubchannelList::SubchannelData::RequestConnectionWithTimer() {
GPR_ASSERT(connectivity_state_ == GRPC_CHANNEL_CONNECTING); GPR_ASSERT(connectivity_state_ == GRPC_CHANNEL_CONNECTING);
} }
// If this is not the last subchannel in the list, start the timer. // If this is not the last subchannel in the list, start the timer.
if (Index() != subchannel_list_->size() - 1) { if (index_ != subchannel_list_->size() - 1) {
PickFirst* p = subchannel_list_->policy_.get(); PickFirst* p = subchannel_list_->policy_.get();
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"Pick First %p subchannel list %p: starting Connection " "Pick First %p subchannel list %p: starting Connection "
"Attempt Delay timer for %" PRId64 "ms for index %" PRIuPTR, "Attempt Delay timer for %" PRId64 "ms for index %" PRIuPTR,
p, subchannel_list_, p->connection_attempt_delay_.millis(), p, subchannel_list_, p->connection_attempt_delay_.millis(),
Index()); index_);
} }
subchannel_list_->timer_handle_ = subchannel_list_->timer_handle_ =
p->channel_control_helper()->GetEventEngine()->RunAfter( p->channel_control_helper()->GetEventEngine()->RunAfter(
@ -1036,7 +1042,7 @@ void PickFirst::SubchannelList::SubchannelData::ProcessUnselectedReadyLocked() {
} }
// Unref all other subchannels in the list. // Unref all other subchannels in the list.
for (size_t i = 0; i < subchannel_list_->size(); ++i) { for (size_t i = 0; i < subchannel_list_->size(); ++i) {
if (i != Index()) { if (i != index_) {
subchannel_list_->subchannels_[i].ShutdownLocked(); subchannel_list_->subchannels_[i].ShutdownLocked();
} }
} }
@ -1047,7 +1053,7 @@ void PickFirst::SubchannelList::SubchannelData::ProcessUnselectedReadyLocked() {
// //
PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy, PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
EndpointAddressesList addresses, EndpointAddressesIterator* addresses,
const ChannelArgs& args) const ChannelArgs& args)
: InternallyRefCounted<SubchannelList>( : InternallyRefCounted<SubchannelList>(
GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace) ? "SubchannelList" GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace) ? "SubchannelList"
@ -1057,14 +1063,12 @@ PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
.Remove( .Remove(
GRPC_ARG_INTERNAL_PICK_FIRST_OMIT_STATUS_MESSAGE_PREFIX)) { GRPC_ARG_INTERNAL_PICK_FIRST_OMIT_STATUS_MESSAGE_PREFIX)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO, "[PF %p] Creating subchannel list %p - channel args: %s",
"[PF %p] Creating subchannel list %p for %" PRIuPTR policy_.get(), this, args_.ToString().c_str());
" subchannels - channel args: %s",
policy_.get(), this, addresses.size(), args_.ToString().c_str());
} }
subchannels_.reserve(addresses.size()); if (addresses == nullptr) return;
// Create a subchannel for each address. // Create a subchannel for each address.
for (const EndpointAddresses& address : addresses) { addresses->ForEach([&](const EndpointAddresses& address) {
GPR_ASSERT(address.addresses().size() == 1); GPR_ASSERT(address.addresses().size() == 1);
RefCountedPtr<SubchannelInterface> subchannel = RefCountedPtr<SubchannelInterface> subchannel =
policy_->channel_control_helper()->CreateSubchannel( policy_->channel_control_helper()->CreateSubchannel(
@ -1076,7 +1080,7 @@ PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
"[PF %p] could not create subchannel for address %s, ignoring", "[PF %p] could not create subchannel for address %s, ignoring",
policy_.get(), address.ToString().c_str()); policy_.get(), address.ToString().c_str());
} }
continue; return;
} }
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
@ -1085,8 +1089,8 @@ PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
policy_.get(), this, subchannels_.size(), subchannel.get(), policy_.get(), this, subchannels_.size(), subchannel.get(),
address.ToString().c_str()); address.ToString().c_str());
} }
subchannels_.emplace_back(this, std::move(subchannel)); subchannels_.emplace_back(this, subchannels_.size(), std::move(subchannel));
} });
} }
PickFirst::SubchannelList::~SubchannelList() { PickFirst::SubchannelList::~SubchannelList() {

@ -684,7 +684,8 @@ absl::Status PriorityLb::ChildPriority::UpdateLocked(
if (priority_policy_->addresses_.ok()) { if (priority_policy_->addresses_.ok()) {
auto it = priority_policy_->addresses_->find(name_); auto it = priority_policy_->addresses_->find(name_);
if (it == priority_policy_->addresses_->end()) { if (it == priority_policy_->addresses_->end()) {
update_args.addresses.emplace(); update_args.addresses = std::make_shared<EndpointAddressesListIterator>(
EndpointAddressesList());
} else { } else {
update_args.addresses = it->second; update_args.addresses = it->second;
} }

@ -554,7 +554,8 @@ void RingHash::RingHashEndpoint::UpdateChildPolicyLocked() {
GPR_ASSERT(config.ok()); GPR_ASSERT(config.ok());
// Update child policy. // Update child policy.
LoadBalancingPolicy::UpdateArgs update_args; LoadBalancingPolicy::UpdateArgs update_args;
update_args.addresses.emplace().emplace_back(ring_hash_->endpoints_[index_]); update_args.addresses =
std::make_shared<SingleEndpointIterator>(ring_hash_->endpoints_[index_]);
update_args.args = ring_hash_->args_; update_args.args = ring_hash_->args_;
update_args.config = std::move(*config); update_args.config = std::move(*config);
// TODO(roth): If the child reports a non-OK status with the update, // TODO(roth): If the child reports a non-OK status with the update,
@ -622,18 +623,14 @@ absl::Status RingHash::UpdateLocked(UpdateArgs args) {
// Check address list. // Check address list.
if (args.addresses.ok()) { if (args.addresses.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
gpr_log(GPR_INFO, "[RH %p] received update with %" PRIuPTR " addresses", gpr_log(GPR_INFO, "[RH %p] received update", this);
this, args.addresses->size());
} }
// De-dup endpoints, taking weight into account. // De-dup endpoints, taking weight into account.
endpoints_.clear(); endpoints_.clear();
endpoints_.reserve(args.addresses->size());
std::map<EndpointAddressSet, size_t> endpoint_indices; std::map<EndpointAddressSet, size_t> endpoint_indices;
size_t num_skipped = 0; (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
for (size_t i = 0; i < args.addresses->size(); ++i) {
EndpointAddresses& endpoint = (*args.addresses)[i];
const EndpointAddressSet key(endpoint.addresses()); const EndpointAddressSet key(endpoint.addresses());
auto p = endpoint_indices.emplace(key, i - num_skipped); auto p = endpoint_indices.emplace(key, endpoints_.size());
if (!p.second) { if (!p.second) {
// Duplicate endpoint. Combine weights and skip the dup. // Duplicate endpoint. Combine weights and skip the dup.
EndpointAddresses& prev_endpoint = endpoints_[p.first->second]; EndpointAddresses& prev_endpoint = endpoints_[p.first->second];
@ -651,11 +648,10 @@ absl::Status RingHash::UpdateLocked(UpdateArgs args) {
prev_endpoint.addresses(), prev_endpoint.addresses(),
prev_endpoint.args().Set(GRPC_ARG_ADDRESS_WEIGHT, prev_endpoint.args().Set(GRPC_ARG_ADDRESS_WEIGHT,
weight_arg + prev_weight_arg)); weight_arg + prev_weight_arg));
++num_skipped;
} else { } else {
endpoints_.push_back(std::move(endpoint)); endpoints_.push_back(endpoint);
} }
} });
} else { } else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
gpr_log(GPR_INFO, "[RH %p] received update with addresses error: %s", gpr_log(GPR_INFO, "[RH %p] received update with addresses error: %s",

@ -707,7 +707,7 @@ class RlsLb : public LoadBalancingPolicy {
OrphanablePtr<RlsChannel> rls_channel_ ABSL_GUARDED_BY(mu_); OrphanablePtr<RlsChannel> rls_channel_ ABSL_GUARDED_BY(mu_);
// Accessed only from within WorkSerializer. // Accessed only from within WorkSerializer.
absl::StatusOr<EndpointAddressesList> addresses_; absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses_;
ChannelArgs channel_args_; ChannelArgs channel_args_;
RefCountedPtr<RlsLbConfig> config_; RefCountedPtr<RlsLbConfig> config_;
RefCountedPtr<ChildPolicyWrapper> default_child_policy_; RefCountedPtr<ChildPolicyWrapper> default_child_policy_;
@ -1858,6 +1858,27 @@ RlsLb::RlsLb(Args args) : LoadBalancingPolicy(std::move(args)), cache_(this) {
} }
} }
bool EndpointsEqual(
const absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> endpoints1,
const absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>>
endpoints2) {
if (endpoints1.status() != endpoints2.status()) return false;
if (endpoints1.ok()) {
std::vector<EndpointAddresses> e1_list;
(*endpoints1)->ForEach([&](const EndpointAddresses& endpoint) {
e1_list.push_back(endpoint);
});
size_t i = 0;
bool different = false;
(*endpoints2)->ForEach([&](const EndpointAddresses& endpoint) {
if (endpoint != e1_list[i++]) different = true;
});
if (different) return false;
if (i != e1_list.size()) return false;
}
return true;
}
absl::Status RlsLb::UpdateLocked(UpdateArgs args) { absl::Status RlsLb::UpdateLocked(UpdateArgs args) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
gpr_log(GPR_INFO, "[rlslb %p] policy updated", this); gpr_log(GPR_INFO, "[rlslb %p] policy updated", this);
@ -1875,7 +1896,7 @@ absl::Status RlsLb::UpdateLocked(UpdateArgs args) {
// Swap out addresses. // Swap out addresses.
// If the new address list is an error and we have an existing address list, // If the new address list is an error and we have an existing address list,
// stick with the existing addresses. // stick with the existing addresses.
absl::StatusOr<EndpointAddressesList> old_addresses; absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> old_addresses;
if (args.addresses.ok()) { if (args.addresses.ok()) {
old_addresses = std::move(addresses_); old_addresses = std::move(addresses_);
addresses_ = std::move(args.addresses); addresses_ = std::move(args.addresses);
@ -1888,7 +1909,7 @@ absl::Status RlsLb::UpdateLocked(UpdateArgs args) {
bool update_child_policies = bool update_child_policies =
old_config == nullptr || old_config == nullptr ||
old_config->child_policy_config() != config_->child_policy_config() || old_config->child_policy_config() != config_->child_policy_config() ||
old_addresses != addresses_ || args.args != channel_args_; !EndpointsEqual(old_addresses, addresses_) || args.args != channel_args_;
// If default target changes, swap out child policy. // If default target changes, swap out child policy.
bool created_default_child = false; bool created_default_child = false;
if (old_config == nullptr || if (old_config == nullptr ||

@ -125,14 +125,14 @@ class OldRoundRobin : public LoadBalancingPolicy {
: public SubchannelList<RoundRobinSubchannelList, : public SubchannelList<RoundRobinSubchannelList,
RoundRobinSubchannelData> { RoundRobinSubchannelData> {
public: public:
RoundRobinSubchannelList(OldRoundRobin* policy, ServerAddressList addresses, RoundRobinSubchannelList(OldRoundRobin* policy,
EndpointAddressesIterator* addresses,
const ChannelArgs& args) const ChannelArgs& args)
: SubchannelList(policy, : SubchannelList(policy,
(GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace) (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)
? "RoundRobinSubchannelList" ? "RoundRobinSubchannelList"
: nullptr), : nullptr),
std::move(addresses), policy->channel_control_helper(), addresses, policy->channel_control_helper(), args) {
args) {
// Need to maintain a ref to the LB policy as long as we maintain // Need to maintain a ref to the LB policy as long as we maintain
// any references to subchannels, since the subchannels' // any references to subchannels, since the subchannels'
// pollset_sets will include the LB policy's pollset_set. // pollset_sets will include the LB policy's pollset_set.
@ -277,13 +277,12 @@ void OldRoundRobin::ResetBackoffLocked() {
} }
absl::Status OldRoundRobin::UpdateLocked(UpdateArgs args) { absl::Status OldRoundRobin::UpdateLocked(UpdateArgs args) {
ServerAddressList addresses; EndpointAddressesIterator* addresses = nullptr;
if (args.addresses.ok()) { if (args.addresses.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses", gpr_log(GPR_INFO, "[RR %p] received update", this);
this, args.addresses->size());
} }
addresses = std::move(*args.addresses); addresses = args.addresses->get();
} else { } else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO, "[RR %p] received update with address error: %s", this, gpr_log(GPR_INFO, "[RR %p] received update with address error: %s", this,
@ -299,8 +298,8 @@ absl::Status OldRoundRobin::UpdateLocked(UpdateArgs args) {
gpr_log(GPR_INFO, "[RR %p] replacing previous pending subchannel list %p", gpr_log(GPR_INFO, "[RR %p] replacing previous pending subchannel list %p",
this, latest_pending_subchannel_list_.get()); this, latest_pending_subchannel_list_.get());
} }
latest_pending_subchannel_list_ = MakeRefCounted<RoundRobinSubchannelList>( latest_pending_subchannel_list_ =
this, std::move(addresses), args.args); MakeRefCounted<RoundRobinSubchannelList>(this, addresses, args.args);
latest_pending_subchannel_list_->StartWatchingLocked(args.args); latest_pending_subchannel_list_->StartWatchingLocked(args.args);
// If the new list is empty, immediately promote it to // If the new list is empty, immediately promote it to
// subchannel_list_ and report TRANSIENT_FAILURE. // subchannel_list_ and report TRANSIENT_FAILURE.
@ -524,7 +523,7 @@ class RoundRobin : public LoadBalancingPolicy {
class RoundRobinEndpointList : public EndpointList { class RoundRobinEndpointList : public EndpointList {
public: public:
RoundRobinEndpointList(RefCountedPtr<RoundRobin> round_robin, RoundRobinEndpointList(RefCountedPtr<RoundRobin> round_robin,
const EndpointAddressesList& endpoints, EndpointAddressesIterator* endpoints,
const ChannelArgs& args) const ChannelArgs& args)
: EndpointList(std::move(round_robin), : EndpointList(std::move(round_robin),
GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace) GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)
@ -687,13 +686,12 @@ void RoundRobin::ResetBackoffLocked() {
} }
absl::Status RoundRobin::UpdateLocked(UpdateArgs args) { absl::Status RoundRobin::UpdateLocked(UpdateArgs args) {
EndpointAddressesList addresses; EndpointAddressesIterator* addresses = nullptr;
if (args.addresses.ok()) { if (args.addresses.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " endpoints", gpr_log(GPR_INFO, "[RR %p] received update", this);
this, args.addresses->size());
} }
addresses = std::move(*args.addresses); addresses = args.addresses->get();
} else { } else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO, "[RR %p] received update with address error: %s", this, gpr_log(GPR_INFO, "[RR %p] received update with address error: %s", this,
@ -710,8 +708,7 @@ absl::Status RoundRobin::UpdateLocked(UpdateArgs args) {
latest_pending_endpoint_list_.get()); latest_pending_endpoint_list_.get());
} }
latest_pending_endpoint_list_ = MakeOrphanable<RoundRobinEndpointList>( latest_pending_endpoint_list_ = MakeOrphanable<RoundRobinEndpointList>(
Ref(DEBUG_LOCATION, "RoundRobinEndpointList"), std::move(addresses), Ref(DEBUG_LOCATION, "RoundRobinEndpointList"), addresses, args.args);
args.args);
// If the new list is empty, immediately promote it to // If the new list is empty, immediately promote it to
// endpoint_list_ and report TRANSIENT_FAILURE. // endpoint_list_ and report TRANSIENT_FAILURE.
if (latest_pending_endpoint_list_->size() == 0) { if (latest_pending_endpoint_list_->size() == 0) {

@ -42,6 +42,7 @@
#include "src/core/lib/iomgr/iomgr_fwd.h" #include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/load_balancing/lb_policy.h" #include "src/core/lib/load_balancing/lb_policy.h"
#include "src/core/lib/load_balancing/subchannel_interface.h" #include "src/core/lib/load_balancing/subchannel_interface.h"
#include "src/core/lib/resolver/endpoint_addresses.h"
#include "src/core/lib/resolver/server_address.h" #include "src/core/lib/resolver/server_address.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
@ -208,7 +209,7 @@ class SubchannelList : public DualRefCounted<SubchannelListType> {
protected: protected:
SubchannelList(LoadBalancingPolicy* policy, const char* tracer, SubchannelList(LoadBalancingPolicy* policy, const char* tracer,
ServerAddressList addresses, EndpointAddressesIterator* addresses,
LoadBalancingPolicy::ChannelControlHelper* helper, LoadBalancingPolicy::ChannelControlHelper* helper,
const ChannelArgs& args); const ChannelArgs& args);
@ -365,19 +366,18 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
template <typename SubchannelListType, typename SubchannelDataType> template <typename SubchannelListType, typename SubchannelDataType>
SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList( SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
LoadBalancingPolicy* policy, const char* tracer, LoadBalancingPolicy* policy, const char* tracer,
ServerAddressList addresses, EndpointAddressesIterator* addresses,
LoadBalancingPolicy::ChannelControlHelper* helper, const ChannelArgs& args) LoadBalancingPolicy::ChannelControlHelper* helper, const ChannelArgs& args)
: DualRefCounted<SubchannelListType>(tracer), : DualRefCounted<SubchannelListType>(tracer),
policy_(policy), policy_(policy),
tracer_(tracer) { tracer_(tracer) {
if (GPR_UNLIKELY(tracer_ != nullptr)) { if (GPR_UNLIKELY(tracer_ != nullptr)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO, "[%s %p] Creating subchannel list %p", tracer_, policy,
"[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels", this);
tracer_, policy, this, addresses.size());
} }
subchannels_.reserve(addresses.size()); if (addresses == nullptr) return;
// Create a subchannel for each address. // Create a subchannel for each address.
for (ServerAddress address : addresses) { addresses->ForEach([&](const EndpointAddresses& address) {
RefCountedPtr<SubchannelInterface> subchannel = RefCountedPtr<SubchannelInterface> subchannel =
helper->CreateSubchannel(address.address(), address.args(), args); helper->CreateSubchannel(address.address(), address.args(), args);
if (subchannel == nullptr) { if (subchannel == nullptr) {
@ -387,7 +387,7 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
"[%s %p] could not create subchannel for address %s, ignoring", "[%s %p] could not create subchannel for address %s, ignoring",
tracer_, policy_, address.ToString().c_str()); tracer_, policy_, address.ToString().c_str());
} }
continue; return;
} }
if (GPR_UNLIKELY(tracer_ != nullptr)) { if (GPR_UNLIKELY(tracer_ != nullptr)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
@ -397,8 +397,8 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
address.ToString().c_str()); address.ToString().c_str());
} }
subchannels_.emplace_back(); subchannels_.emplace_back();
subchannels_.back().Init(this, std::move(address), std::move(subchannel)); subchannels_.back().Init(this, address, std::move(subchannel));
} });
} }
template <typename SubchannelListType, typename SubchannelDataType> template <typename SubchannelListType, typename SubchannelDataType>

@ -247,14 +247,13 @@ class OldWeightedRoundRobin : public LoadBalancingPolicy {
WeightedRoundRobinSubchannelData> { WeightedRoundRobinSubchannelData> {
public: public:
WeightedRoundRobinSubchannelList(OldWeightedRoundRobin* policy, WeightedRoundRobinSubchannelList(OldWeightedRoundRobin* policy,
ServerAddressList addresses, EndpointAddressesIterator* addresses,
const ChannelArgs& args) const ChannelArgs& args)
: SubchannelList(policy, : SubchannelList(policy,
(GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace) (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)
? "WeightedRoundRobinSubchannelList" ? "WeightedRoundRobinSubchannelList"
: nullptr), : nullptr),
std::move(addresses), policy->channel_control_helper(), addresses, policy->channel_control_helper(), args) {
args) {
// Need to maintain a ref to the LB policy as long as we maintain // Need to maintain a ref to the LB policy as long as we maintain
// any references to subchannels, since the subchannels' // any references to subchannels, since the subchannels'
// pollset_sets will include the LB policy's pollset_set. // pollset_sets will include the LB policy's pollset_set.
@ -675,11 +674,10 @@ void OldWeightedRoundRobin::ResetBackoffLocked() {
absl::Status OldWeightedRoundRobin::UpdateLocked(UpdateArgs args) { absl::Status OldWeightedRoundRobin::UpdateLocked(UpdateArgs args) {
global_stats().IncrementWrrUpdates(); global_stats().IncrementWrrUpdates();
config_ = std::move(args.config); config_ = std::move(args.config);
ServerAddressList addresses; std::shared_ptr<EndpointAddressesIterator> addresses;
if (args.addresses.ok()) { if (args.addresses.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
gpr_log(GPR_INFO, "[WRR %p] received update with %" PRIuPTR " addresses", gpr_log(GPR_INFO, "[WRR %p] received update", this);
this, args.addresses->size());
} }
// Weed out duplicate addresses. Also sort the addresses so that if // Weed out duplicate addresses. Also sort the addresses so that if
// the set of the addresses don't change, their indexes in the // the set of the addresses don't change, their indexes in the
@ -698,10 +696,12 @@ absl::Status OldWeightedRoundRobin::UpdateLocked(UpdateArgs args) {
return memcmp(addr1.addr, addr2.addr, addr1.len) < 0; return memcmp(addr1.addr, addr2.addr, addr1.len) < 0;
} }
}; };
std::set<ServerAddress, AddressLessThan> ordered_addresses( std::set<ServerAddress, AddressLessThan> ordered_addresses;
args.addresses->begin(), args.addresses->end()); (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
addresses = ordered_addresses.insert(endpoint);
ServerAddressList(ordered_addresses.begin(), ordered_addresses.end()); });
addresses = std::make_shared<EndpointAddressesListIterator>(
ServerAddressList(ordered_addresses.begin(), ordered_addresses.end()));
} else { } else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
gpr_log(GPR_INFO, "[WRR %p] received update with address error: %s", this, gpr_log(GPR_INFO, "[WRR %p] received update with address error: %s", this,
@ -718,8 +718,8 @@ absl::Status OldWeightedRoundRobin::UpdateLocked(UpdateArgs args) {
this, latest_pending_subchannel_list_.get()); this, latest_pending_subchannel_list_.get());
} }
latest_pending_subchannel_list_ = latest_pending_subchannel_list_ =
MakeRefCounted<WeightedRoundRobinSubchannelList>( MakeRefCounted<WeightedRoundRobinSubchannelList>(this, addresses.get(),
this, std::move(addresses), args.args); args.args);
latest_pending_subchannel_list_->StartWatchingLocked(args.args); latest_pending_subchannel_list_->StartWatchingLocked(args.args);
// If the new list is empty, immediately promote it to // If the new list is empty, immediately promote it to
// subchannel_list_ and report TRANSIENT_FAILURE. // subchannel_list_ and report TRANSIENT_FAILURE.
@ -1079,7 +1079,7 @@ class WeightedRoundRobin : public LoadBalancingPolicy {
}; };
WrrEndpointList(RefCountedPtr<WeightedRoundRobin> wrr, WrrEndpointList(RefCountedPtr<WeightedRoundRobin> wrr,
const EndpointAddressesList& endpoints, EndpointAddressesIterator* endpoints,
const ChannelArgs& args) const ChannelArgs& args)
: EndpointList(std::move(wrr), : EndpointList(std::move(wrr),
GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace) GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)
@ -1516,11 +1516,10 @@ void WeightedRoundRobin::ResetBackoffLocked() {
absl::Status WeightedRoundRobin::UpdateLocked(UpdateArgs args) { absl::Status WeightedRoundRobin::UpdateLocked(UpdateArgs args) {
global_stats().IncrementWrrUpdates(); global_stats().IncrementWrrUpdates();
config_ = std::move(args.config); config_ = std::move(args.config);
EndpointAddressesList addresses; std::shared_ptr<EndpointAddressesIterator> addresses;
if (args.addresses.ok()) { if (args.addresses.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
gpr_log(GPR_INFO, "[WRR %p] received update with %" PRIuPTR " addresses", gpr_log(GPR_INFO, "[WRR %p] received update", this);
this, args.addresses->size());
} }
// Weed out duplicate endpoints. Also sort the endpoints so that if // Weed out duplicate endpoints. Also sort the endpoints so that if
// the set of endpoints doesn't change, their indexes in the endpoint // the set of endpoints doesn't change, their indexes in the endpoint
@ -1539,10 +1538,13 @@ absl::Status WeightedRoundRobin::UpdateLocked(UpdateArgs args) {
return e1 < e2; return e1 < e2;
} }
}; };
std::set<EndpointAddresses, EndpointAddressesLessThan> ordered_addresses( std::set<EndpointAddresses, EndpointAddressesLessThan> ordered_addresses;
args.addresses->begin(), args.addresses->end()); (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
addresses = EndpointAddressesList(ordered_addresses.begin(), ordered_addresses.insert(endpoint);
ordered_addresses.end()); });
addresses =
std::make_shared<EndpointAddressesListIterator>(EndpointAddressesList(
ordered_addresses.begin(), ordered_addresses.end()));
} else { } else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
gpr_log(GPR_INFO, "[WRR %p] received update with address error: %s", this, gpr_log(GPR_INFO, "[WRR %p] received update with address error: %s", this,
@ -1559,7 +1561,7 @@ absl::Status WeightedRoundRobin::UpdateLocked(UpdateArgs args) {
this, latest_pending_endpoint_list_.get()); this, latest_pending_endpoint_list_.get());
} }
latest_pending_endpoint_list_ = latest_pending_endpoint_list_ =
MakeOrphanable<WrrEndpointList>(Ref(), std::move(addresses), args.args); MakeOrphanable<WrrEndpointList>(Ref(), addresses.get(), args.args);
// If the new list is empty, immediately promote it to // If the new list is empty, immediately promote it to
// endpoint_list_ and report TRANSIENT_FAILURE. // endpoint_list_ and report TRANSIENT_FAILURE.
if (latest_pending_endpoint_list_->size() == 0) { if (latest_pending_endpoint_list_->size() == 0) {

@ -157,10 +157,10 @@ class WeightedTargetLb : public LoadBalancingPolicy {
void Orphan() override; void Orphan() override;
absl::Status UpdateLocked(const WeightedTargetLbConfig::ChildConfig& config, absl::Status UpdateLocked(
absl::StatusOr<EndpointAddressesList> addresses, const WeightedTargetLbConfig::ChildConfig& config,
const std::string& resolution_note, absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses,
const ChannelArgs& args); const std::string& resolution_note, const ChannelArgs& args);
void ResetBackoffLocked(); void ResetBackoffLocked();
void DeactivateLocked(); void DeactivateLocked();
@ -338,11 +338,12 @@ absl::Status WeightedTargetLb::UpdateLocked(UpdateArgs args) {
target = MakeOrphanable<WeightedChild>( target = MakeOrphanable<WeightedChild>(
Ref(DEBUG_LOCATION, "WeightedChild"), name); Ref(DEBUG_LOCATION, "WeightedChild"), name);
} }
absl::StatusOr<EndpointAddressesList> addresses; absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses;
if (address_map.ok()) { if (address_map.ok()) {
auto it = address_map->find(name); auto it = address_map->find(name);
if (it == address_map->end()) { if (it == address_map->end()) {
addresses.emplace(); addresses = std::make_shared<EndpointAddressesListIterator>(
EndpointAddressesList());
} else { } else {
addresses = std::move(it->second); addresses = std::move(it->second);
} }
@ -589,7 +590,7 @@ WeightedTargetLb::WeightedChild::CreateChildPolicyLocked(
absl::Status WeightedTargetLb::WeightedChild::UpdateLocked( absl::Status WeightedTargetLb::WeightedChild::UpdateLocked(
const WeightedTargetLbConfig::ChildConfig& config, const WeightedTargetLbConfig::ChildConfig& config,
absl::StatusOr<EndpointAddressesList> addresses, absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses,
const std::string& resolution_note, const ChannelArgs& args) { const std::string& resolution_note, const ChannelArgs& args) {
if (weighted_target_policy_->shutting_down_) return absl::OkStatus(); if (weighted_target_policy_->shutting_down_) return absl::OkStatus();
// Update child weight. // Update child weight.

@ -199,8 +199,21 @@ class CdsLb : public LoadBalancingPolicy {
// The root of the tree is config_->cluster(). // The root of the tree is config_->cluster().
std::map<std::string, WatcherState> watchers_; std::map<std::string, WatcherState> watchers_;
// TODO(roth, yashkt): These are here because XdsCertificateProvider
// does not store the actual underlying cert providers, it stores only
// their distributors, so we need to hold a ref to the cert providers
// here. However, in the aggregate cluster case, there may be multiple
// clusters in the same cert provider, and we're only tracking the cert
// providers for the most recent underlying cluster here. This is
// clearly a bug, and I think it will cause us to stop getting updates
// for all but one of the cert providers in the aggregate cluster
// case. Need to figure out the right way to fix this -- I don't
// think we want to store another map here, so ideally, we should just
// have XdsCertificateProvider actually hold the refs to the cert
// providers instead of just the distributors.
RefCountedPtr<grpc_tls_certificate_provider> root_certificate_provider_; RefCountedPtr<grpc_tls_certificate_provider> root_certificate_provider_;
RefCountedPtr<grpc_tls_certificate_provider> identity_certificate_provider_; RefCountedPtr<grpc_tls_certificate_provider> identity_certificate_provider_;
RefCountedPtr<XdsCertificateProvider> xds_certificate_provider_; RefCountedPtr<XdsCertificateProvider> xds_certificate_provider_;
// Child LB policy. // Child LB policy.
@ -594,20 +607,7 @@ absl::Status CdsLb::UpdateXdsCertificateProvider(
root_provider_instance_name, "\" not recognized.")); root_provider_instance_name, "\" not recognized."));
} }
} }
if (root_certificate_provider_ != new_root_provider) { root_certificate_provider_ = std::move(new_root_provider);
if (root_certificate_provider_ != nullptr &&
root_certificate_provider_->interested_parties() != nullptr) {
grpc_pollset_set_del_pollset_set(
interested_parties(),
root_certificate_provider_->interested_parties());
}
if (new_root_provider != nullptr &&
new_root_provider->interested_parties() != nullptr) {
grpc_pollset_set_add_pollset_set(interested_parties(),
new_root_provider->interested_parties());
}
root_certificate_provider_ = std::move(new_root_provider);
}
xds_certificate_provider_->UpdateRootCertNameAndDistributor( xds_certificate_provider_->UpdateRootCertNameAndDistributor(
cluster_name, root_provider_cert_name, cluster_name, root_provider_cert_name,
root_certificate_provider_ == nullptr root_certificate_provider_ == nullptr
@ -631,20 +631,7 @@ absl::Status CdsLb::UpdateXdsCertificateProvider(
identity_provider_instance_name, "\" not recognized.")); identity_provider_instance_name, "\" not recognized."));
} }
} }
if (identity_certificate_provider_ != new_identity_provider) { identity_certificate_provider_ = std::move(new_identity_provider);
if (identity_certificate_provider_ != nullptr &&
identity_certificate_provider_->interested_parties() != nullptr) {
grpc_pollset_set_del_pollset_set(
interested_parties(),
identity_certificate_provider_->interested_parties());
}
if (new_identity_provider != nullptr &&
new_identity_provider->interested_parties() != nullptr) {
grpc_pollset_set_add_pollset_set(
interested_parties(), new_identity_provider->interested_parties());
}
identity_certificate_provider_ = std::move(new_identity_provider);
}
xds_certificate_provider_->UpdateIdentityCertNameAndDistributor( xds_certificate_provider_->UpdateIdentityCertNameAndDistributor(
cluster_name, identity_provider_cert_name, cluster_name, identity_provider_cert_name,
identity_certificate_provider_ == nullptr identity_certificate_provider_ == nullptr

@ -250,7 +250,7 @@ class XdsClusterImplLb : public LoadBalancingPolicy {
OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked( OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
const ChannelArgs& args); const ChannelArgs& args);
absl::Status UpdateChildPolicyLocked( absl::Status UpdateChildPolicyLocked(
absl::StatusOr<EndpointAddressesList> addresses, absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses,
std::string resolution_note, const ChannelArgs& args); std::string resolution_note, const ChannelArgs& args);
void MaybeUpdatePickerLocked(); void MaybeUpdatePickerLocked();
@ -569,7 +569,7 @@ OrphanablePtr<LoadBalancingPolicy> XdsClusterImplLb::CreateChildPolicyLocked(
} }
absl::Status XdsClusterImplLb::UpdateChildPolicyLocked( absl::Status XdsClusterImplLb::UpdateChildPolicyLocked(
absl::StatusOr<EndpointAddressesList> addresses, absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>> addresses,
std::string resolution_note, const ChannelArgs& args) { std::string resolution_note, const ChannelArgs& args) {
// Create policy if needed. // Create policy if needed.
if (child_policy_ == nullptr) { if (child_policy_ == nullptr) {

@ -149,7 +149,8 @@ class XdsClusterManagerLb : public LoadBalancingPolicy {
absl::Status UpdateLocked( absl::Status UpdateLocked(
RefCountedPtr<LoadBalancingPolicy::Config> config, RefCountedPtr<LoadBalancingPolicy::Config> config,
const absl::StatusOr<EndpointAddressesList>& addresses, const absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>>&
addresses,
const ChannelArgs& args); const ChannelArgs& args);
void ExitIdleLocked(); void ExitIdleLocked();
void ResetBackoffLocked(); void ResetBackoffLocked();
@ -482,7 +483,7 @@ XdsClusterManagerLb::ClusterChild::CreateChildPolicyLocked(
absl::Status XdsClusterManagerLb::ClusterChild::UpdateLocked( absl::Status XdsClusterManagerLb::ClusterChild::UpdateLocked(
RefCountedPtr<LoadBalancingPolicy::Config> config, RefCountedPtr<LoadBalancingPolicy::Config> config,
const absl::StatusOr<EndpointAddressesList>& addresses, const absl::StatusOr<std::shared_ptr<EndpointAddressesIterator>>& addresses,
const ChannelArgs& args) { const ChannelArgs& args) {
if (xds_cluster_manager_policy_->shutting_down_) return absl::OkStatus(); if (xds_cluster_manager_policy_->shutting_down_) return absl::OkStatus();
// Update child weight. // Update child weight.

@ -28,6 +28,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "absl/functional/function_ref.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
@ -61,6 +62,7 @@
#include "src/core/lib/gprpp/validation_errors.h" #include "src/core/lib/gprpp/validation_errors.h"
#include "src/core/lib/gprpp/work_serializer.h" #include "src/core/lib/gprpp/work_serializer.h"
#include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/iomgr/resolved_address.h"
#include "src/core/lib/json/json.h" #include "src/core/lib/json/json.h"
#include "src/core/lib/json/json_args.h" #include "src/core/lib/json/json_args.h"
#include "src/core/lib/json/json_object_loader.h" #include "src/core/lib/json/json_object_loader.h"
@ -390,7 +392,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy {
absl::Status UpdateChildPolicyLocked(); absl::Status UpdateChildPolicyLocked();
OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked( OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
const ChannelArgs& args); const ChannelArgs& args);
EndpointAddressesList CreateChildPolicyAddressesLocked(); std::shared_ptr<EndpointAddressesIterator> CreateChildPolicyAddressesLocked();
std::string CreateChildPolicyResolutionNoteLocked(); std::string CreateChildPolicyResolutionNoteLocked();
RefCountedPtr<Config> CreateChildPolicyConfigLocked(); RefCountedPtr<Config> CreateChildPolicyConfigLocked();
ChannelArgs CreateChildPolicyArgsLocked(const ChannelArgs& args_in); ChannelArgs CreateChildPolicyArgsLocked(const ChannelArgs& args_in);
@ -529,10 +531,16 @@ XdsClusterResolverLb::DiscoveryMechanismEntry::config() const {
->config_->discovery_mechanisms()[discovery_mechanism->index()]; ->config_->discovery_mechanisms()[discovery_mechanism->index()];
} }
std::string MakeChildPolicyName(absl::string_view cluster_name,
size_t child_number) {
return absl::StrCat("{cluster=", cluster_name,
", child_number=", child_number, "}");
}
std::string XdsClusterResolverLb::DiscoveryMechanismEntry::GetChildPolicyName( std::string XdsClusterResolverLb::DiscoveryMechanismEntry::GetChildPolicyName(
size_t priority) const { size_t priority) const {
return absl::StrCat("{cluster=", config().cluster_name, return MakeChildPolicyName(config().cluster_name,
", child_number=", priority_child_numbers[priority], "}"); priority_child_numbers[priority]);
} }
// //
@ -768,39 +776,76 @@ void XdsClusterResolverLb::OnResourceDoesNotExist(size_t index,
// child policy-related methods // child policy-related methods
// //
EndpointAddressesList XdsClusterResolverLb::CreateChildPolicyAddressesLocked() { class PriorityEndpointIterator : public EndpointAddressesIterator {
EndpointAddressesList addresses; public:
for (const auto& discovery_entry : discovery_mechanisms_) { struct DiscoveryMechanismResult {
const auto& priority_list = std::shared_ptr<const XdsEndpointResource> update;
GetUpdatePriorityList(*discovery_entry.latest_update); std::string cluster_name;
for (size_t priority = 0; priority < priority_list.size(); ++priority) { std::vector<size_t /*child_number*/> priority_child_numbers;
const auto& priority_entry = priority_list[priority];
std::string priority_child_name = DiscoveryMechanismResult(
discovery_entry.GetChildPolicyName(priority); std::shared_ptr<const XdsEndpointResource> resource,
for (const auto& p : priority_entry.localities) { std::string cluster, std::vector<size_t> child_numbers)
const auto& locality_name = p.first; : update(std::move(resource)),
const auto& locality = p.second; cluster_name(std::move(cluster)),
std::vector<RefCountedStringValue> hierarchical_path = { priority_child_numbers(std::move(child_numbers)) {}
RefCountedStringValue(priority_child_name),
RefCountedStringValue(locality_name->AsHumanReadableString())}; std::string GetChildPolicyName(size_t priority) const {
auto hierarchical_path_attr = return MakeChildPolicyName(cluster_name,
MakeRefCounted<HierarchicalPathArg>(std::move(hierarchical_path)); priority_child_numbers[priority]);
for (const auto& endpoint : locality.endpoints) { }
uint32_t endpoint_weight = };
locality.lb_weight *
endpoint.args().GetInt(GRPC_ARG_ADDRESS_WEIGHT).value_or(1); explicit PriorityEndpointIterator(
addresses.emplace_back( std::vector<DiscoveryMechanismResult> results)
endpoint.addresses(), : results_(std::move(results)) {}
endpoint.args()
.SetObject(hierarchical_path_attr) void ForEach(absl::FunctionRef<void(const EndpointAddresses&)> callback)
.Set(GRPC_ARG_ADDRESS_WEIGHT, endpoint_weight) const override {
.SetObject(locality_name->Ref()) for (const auto& entry : results_) {
.Set(GRPC_ARG_XDS_LOCALITY_WEIGHT, locality.lb_weight)); const auto& priority_list = GetUpdatePriorityList(*entry.update);
for (size_t priority = 0; priority < priority_list.size(); ++priority) {
const auto& priority_entry = priority_list[priority];
std::string priority_child_name = entry.GetChildPolicyName(priority);
for (const auto& p : priority_entry.localities) {
const auto& locality_name = p.first;
const auto& locality = p.second;
std::vector<RefCountedStringValue> hierarchical_path = {
RefCountedStringValue(priority_child_name),
RefCountedStringValue(locality_name->AsHumanReadableString())};
auto hierarchical_path_attr =
MakeRefCounted<HierarchicalPathArg>(std::move(hierarchical_path));
for (const auto& endpoint : locality.endpoints) {
uint32_t endpoint_weight =
locality.lb_weight *
endpoint.args().GetInt(GRPC_ARG_ADDRESS_WEIGHT).value_or(1);
callback(EndpointAddresses(
endpoint.addresses(),
endpoint.args()
.SetObject(hierarchical_path_attr)
.Set(GRPC_ARG_ADDRESS_WEIGHT, endpoint_weight)
.SetObject(locality_name->Ref())
.Set(GRPC_ARG_XDS_LOCALITY_WEIGHT, locality.lb_weight)));
}
} }
} }
} }
} }
return addresses;
private:
std::vector<DiscoveryMechanismResult> results_;
};
std::shared_ptr<EndpointAddressesIterator>
XdsClusterResolverLb::CreateChildPolicyAddressesLocked() {
std::vector<PriorityEndpointIterator::DiscoveryMechanismResult> entries;
entries.reserve(discovery_mechanisms_.size());
for (const auto& discovery_entry : discovery_mechanisms_) {
entries.emplace_back(discovery_entry.latest_update,
discovery_entry.config().cluster_name,
discovery_entry.priority_child_numbers);
}
return std::make_shared<PriorityEndpointIterator>(std::move(entries));
} }
std::string XdsClusterResolverLb::CreateChildPolicyResolutionNoteLocked() { std::string XdsClusterResolverLb::CreateChildPolicyResolutionNoteLocked() {

@ -18,7 +18,6 @@
#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.h" #include "src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.h"
#include <inttypes.h>
#include <stddef.h> #include <stddef.h>
#include <algorithm> #include <algorithm>
@ -34,6 +33,7 @@
#include <vector> #include <vector>
#include "absl/base/thread_annotations.h" #include "absl/base/thread_annotations.h"
#include "absl/functional/function_ref.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
@ -300,8 +300,7 @@ class XdsOverrideHostLb : public LoadBalancingPolicy {
void MaybeUpdatePickerLocked(); void MaybeUpdatePickerLocked();
absl::StatusOr<EndpointAddressesList> UpdateAddressMap( void UpdateAddressMap(const EndpointAddressesIterator& endpoints);
absl::StatusOr<EndpointAddressesList> endpoints);
RefCountedPtr<SubchannelWrapper> AdoptSubchannel( RefCountedPtr<SubchannelWrapper> AdoptSubchannel(
const grpc_resolved_address& address, const grpc_resolved_address& address,
@ -508,12 +507,36 @@ void XdsOverrideHostLb::ResetBackoffLocked() {
if (child_policy_ != nullptr) child_policy_->ResetBackoffLocked(); if (child_policy_ != nullptr) child_policy_->ResetBackoffLocked();
} }
// Wraps the endpoint iterator and filters out endpoints in state DRAINING.
class ChildEndpointIterator : public EndpointAddressesIterator {
public:
explicit ChildEndpointIterator(
std::shared_ptr<EndpointAddressesIterator> parent_it)
: parent_it_(std::move(parent_it)) {}
void ForEach(absl::FunctionRef<void(const EndpointAddresses&)> callback)
const override {
parent_it_->ForEach([&](const EndpointAddresses& endpoint) {
XdsHealthStatus status = GetEndpointHealthStatus(endpoint);
if (status.status() != XdsHealthStatus::kDraining) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO,
"[xds_override_host_lb %p] endpoint %s: not draining, "
"passing to child",
this, endpoint.ToString().c_str());
}
callback(endpoint);
}
});
}
private:
std::shared_ptr<EndpointAddressesIterator> parent_it_;
};
absl::Status XdsOverrideHostLb::UpdateLocked(UpdateArgs args) { absl::Status XdsOverrideHostLb::UpdateLocked(UpdateArgs args) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO, "[xds_override_host_lb %p] Received update", this);
"[xds_override_host_lb %p] Received update with %" PRIuPTR
" addresses",
this, args.addresses.ok() ? args.addresses->size() : 0);
} }
auto old_config = std::move(config_); auto old_config = std::move(config_);
// Update config. // Update config.
@ -521,13 +544,24 @@ absl::Status XdsOverrideHostLb::UpdateLocked(UpdateArgs args) {
if (config_ == nullptr) { if (config_ == nullptr) {
return absl::InvalidArgumentError("Missing policy config"); return absl::InvalidArgumentError("Missing policy config");
} }
// Update address map and wrap endpoint iterator for child policy.
if (args.addresses.ok()) {
UpdateAddressMap(**args.addresses);
args.addresses =
std::make_shared<ChildEndpointIterator>(std::move(*args.addresses));
} else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO, "[xds_override_host_lb %p] address error: %s", this,
args.addresses.status().ToString().c_str());
}
}
// Create child policy if needed. // Create child policy if needed.
if (child_policy_ == nullptr) { if (child_policy_ == nullptr) {
child_policy_ = CreateChildPolicyLocked(args.args); child_policy_ = CreateChildPolicyLocked(args.args);
} }
// Update child policy. // Update child policy.
UpdateArgs update_args; UpdateArgs update_args;
update_args.addresses = UpdateAddressMap(std::move(args.addresses)); update_args.addresses = std::move(args.addresses);
update_args.resolution_note = std::move(args.resolution_note); update_args.resolution_note = std::move(args.resolution_note);
update_args.config = config_->child_config(); update_args.config = config_->child_config();
update_args.args = std::move(args.args); update_args.args = std::move(args.args);
@ -578,18 +612,9 @@ OrphanablePtr<LoadBalancingPolicy> XdsOverrideHostLb::CreateChildPolicyLocked(
return lb_policy; return lb_policy;
} }
absl::StatusOr<EndpointAddressesList> XdsOverrideHostLb::UpdateAddressMap( void XdsOverrideHostLb::UpdateAddressMap(
absl::StatusOr<EndpointAddressesList> endpoints) { const EndpointAddressesIterator& endpoints) {
if (!endpoints.ok()) { // Construct a map of address info from which to update subchannel_map_.
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO, "[xds_override_host_lb %p] address error: %s", this,
endpoints.status().ToString().c_str());
}
return endpoints;
}
// Construct the list of addresses to pass to the child policy and a
// map of address info from which to update subchannel_map_.
EndpointAddressesList child_addresses;
struct AddressInfo { struct AddressInfo {
XdsHealthStatus eds_health_status; XdsHealthStatus eds_health_status;
RefCountedStringValue address_list; RefCountedStringValue address_list;
@ -597,25 +622,18 @@ absl::StatusOr<EndpointAddressesList> XdsOverrideHostLb::UpdateAddressMap(
: eds_health_status(status), address_list(std::move(addresses)) {} : eds_health_status(status), address_list(std::move(addresses)) {}
}; };
std::map<const std::string, AddressInfo> addresses_for_map; std::map<const std::string, AddressInfo> addresses_for_map;
for (const auto& endpoint : *endpoints) { endpoints.ForEach([&](const EndpointAddresses& endpoint) {
XdsHealthStatus status = GetEndpointHealthStatus(endpoint); XdsHealthStatus status = GetEndpointHealthStatus(endpoint);
if (status.status() != XdsHealthStatus::kDraining) { // Skip draining hosts if not in the override status set.
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) { if (status.status() == XdsHealthStatus::kDraining &&
gpr_log(GPR_INFO, !config_->override_host_status_set().Contains(status)) {
"[xds_override_host_lb %p] endpoint %s: not draining, "
"passing to child",
this, endpoint.ToString().c_str());
}
child_addresses.push_back(endpoint);
} else if (!config_->override_host_status_set().Contains(status)) {
// Skip draining hosts if not in the override status set.
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[xds_override_host_lb %p] endpoint %s: draining but not in " "[xds_override_host_lb %p] endpoint %s: draining but not in "
"override_host_status set -- ignoring", "override_host_status set -- ignoring",
this, endpoint.ToString().c_str()); this, endpoint.ToString().c_str());
} }
continue; return;
} }
std::vector<std::string> addresses; std::vector<std::string> addresses;
addresses.reserve(endpoint.addresses().size()); addresses.reserve(endpoint.addresses().size());
@ -641,7 +659,7 @@ absl::StatusOr<EndpointAddressesList> XdsOverrideHostLb::UpdateAddressMap(
std::piecewise_construct, std::forward_as_tuple(addresses[i]), std::piecewise_construct, std::forward_as_tuple(addresses[i]),
std::forward_as_tuple(status, std::move(address_list))); std::forward_as_tuple(status, std::move(address_list)));
} }
} });
// Now grab the lock and update subchannel_map_ from addresses_for_map. // Now grab the lock and update subchannel_map_ from addresses_for_map.
{ {
MutexLock lock(&subchannel_map_mu_); MutexLock lock(&subchannel_map_mu_);
@ -688,7 +706,6 @@ absl::StatusOr<EndpointAddressesList> XdsOverrideHostLb::UpdateAddressMap(
it->second.set_address_list(std::move(address_info.address_list)); it->second.set_address_list(std::move(address_info.address_list));
} }
} }
return child_addresses;
} }
RefCountedPtr<XdsOverrideHostLb::SubchannelWrapper> RefCountedPtr<XdsOverrideHostLb::SubchannelWrapper>

@ -21,7 +21,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
@ -170,10 +169,10 @@ absl::Status XdsWrrLocalityLb::UpdateLocked(UpdateArgs args) {
// Scan the addresses to find the weight for each locality. // Scan the addresses to find the weight for each locality.
std::map<std::string, uint32_t> locality_weights; std::map<std::string, uint32_t> locality_weights;
if (args.addresses.ok()) { if (args.addresses.ok()) {
for (const auto& address : *args.addresses) { (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
auto* locality_name = address.args().GetObject<XdsLocalityName>(); auto* locality_name = endpoint.args().GetObject<XdsLocalityName>();
uint32_t weight = uint32_t weight =
address.args().GetInt(GRPC_ARG_XDS_LOCALITY_WEIGHT).value_or(0); endpoint.args().GetInt(GRPC_ARG_XDS_LOCALITY_WEIGHT).value_or(0);
if (locality_name != nullptr && weight > 0) { if (locality_name != nullptr && weight > 0) {
auto p = locality_weights.emplace( auto p = locality_weights.emplace(
locality_name->AsHumanReadableString(), weight); locality_name->AsHumanReadableString(), weight);
@ -184,7 +183,7 @@ absl::Status XdsWrrLocalityLb::UpdateLocked(UpdateArgs args) {
p.first->first.c_str(), p.first->second, weight); p.first->first.c_str(), p.first->second, weight);
} }
} }
} });
} }
// Construct the config for the weighted_target policy. // Construct the config for the weighted_target policy.
Json::Object weighted_targets; Json::Object weighted_targets;

@ -22,10 +22,9 @@
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include <memory> #include <memory>
#include <type_traits>
#include <utility> #include <utility>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -36,9 +35,7 @@
#include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/work_serializer.h" #include "src/core/lib/gprpp/work_serializer.h"
#include "src/core/lib/resolver/endpoint_addresses.h"
#include "src/core/lib/resolver/resolver_factory.h" #include "src/core/lib/resolver/resolver_factory.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/uri/uri_parser.h" #include "src/core/lib/uri/uri_parser.h"
namespace grpc_core { namespace grpc_core {
@ -55,47 +52,38 @@ class FakeResolver : public Resolver {
private: private:
friend class FakeResolverResponseGenerator; friend class FakeResolverResponseGenerator;
friend class FakeResolverResponseSetter;
void ShutdownLocked() override; void ShutdownLocked() override;
void MaybeSendResultLocked(); void MaybeSendResultLocked();
void ReturnReresolutionResult();
// passed-in parameters // passed-in parameters
ChannelArgs channel_args_;
std::shared_ptr<WorkSerializer> work_serializer_; std::shared_ptr<WorkSerializer> work_serializer_;
std::unique_ptr<ResultHandler> result_handler_; std::unique_ptr<ResultHandler> result_handler_;
ChannelArgs channel_args_;
RefCountedPtr<FakeResolverResponseGenerator> response_generator_; RefCountedPtr<FakeResolverResponseGenerator> response_generator_;
// If has_next_result_ is true, next_result_ is the next resolution result // The next resolution result to be returned, if any. Present when we
// to be returned. // get a result before the resolver is started.
bool has_next_result_ = false; absl::optional<Result> next_result_;
Result next_result_;
// Result to use for the pretended re-resolution in
// RequestReresolutionLocked().
bool has_reresolution_result_ = false;
Result reresolution_result_;
// True after the call to StartLocked(). // True after the call to StartLocked().
bool started_ = false; bool started_ = false;
// True after the call to ShutdownLocked(). // True after the call to ShutdownLocked().
bool shutdown_ = false; bool shutdown_ = false;
// if true, return failure
bool return_failure_ = false;
// pending re-resolution
bool reresolution_closure_pending_ = false;
}; };
FakeResolver::FakeResolver(ResolverArgs args) FakeResolver::FakeResolver(ResolverArgs args)
: work_serializer_(std::move(args.work_serializer)), : work_serializer_(std::move(args.work_serializer)),
result_handler_(std::move(args.result_handler)), result_handler_(std::move(args.result_handler)),
channel_args_(
// Channels sharing the same subchannels may have different resolver
// response generators. If we don't remove this arg, subchannel pool
// will create new subchannels for the same address instead of
// reusing existing ones because of different values of this channel
// arg. Can't just use GRPC_ARG_NO_SUBCHANNEL_PREFIX, since
// that can't be passed into the channel from test code.
args.args.Remove(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR)),
response_generator_( response_generator_(
args.args.GetObjectRef<FakeResolverResponseGenerator>()) { args.args.GetObjectRef<FakeResolverResponseGenerator>()) {
// Channels sharing the same subchannels may have different resolver response
// generators. If we don't remove this arg, subchannel pool will create new
// subchannels for the same address instead of reusing existing ones because
// of different values of this channel arg.
channel_args_ = args.args.Remove(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
if (response_generator_ != nullptr) { if (response_generator_ != nullptr) {
response_generator_->SetFakeResolver(Ref()); response_generator_->SetFakeResolver(Ref());
} }
@ -107,19 +95,9 @@ void FakeResolver::StartLocked() {
} }
void FakeResolver::RequestReresolutionLocked() { void FakeResolver::RequestReresolutionLocked() {
if (has_reresolution_result_ || return_failure_) { // Re-resolution can't happen until after we return an initial result.
next_result_ = reresolution_result_; GPR_ASSERT(response_generator_ != nullptr);
has_next_result_ = true; response_generator_->ReresolutionRequested();
// Return the result in a different closure, so that we don't call
// back into the LB policy while it's still processing the previous
// update.
if (!reresolution_closure_pending_) {
reresolution_closure_pending_ = true;
Ref().release(); // ref held by closure
work_serializer_->Run([this]() { ReturnReresolutionResult(); },
DEBUG_LOCATION);
}
}
} }
void FakeResolver::ShutdownLocked() { void FakeResolver::ShutdownLocked() {
@ -132,80 +110,15 @@ void FakeResolver::ShutdownLocked() {
void FakeResolver::MaybeSendResultLocked() { void FakeResolver::MaybeSendResultLocked() {
if (!started_ || shutdown_) return; if (!started_ || shutdown_) return;
if (return_failure_) { if (next_result_.has_value()) {
// TODO(roth): Change resolver result generator to be able to inject
// the error to be returned and to be able to independently set errors
// for addresses and service config.
Result result;
result.addresses = absl::UnavailableError("Resolver transient failure");
result.service_config = result.addresses.status();
result.args = channel_args_;
result_handler_->ReportResult(std::move(result));
return_failure_ = false;
} else if (has_next_result_) {
// When both next_results_ and channel_args_ contain an arg with the same // When both next_results_ and channel_args_ contain an arg with the same
// name, only the one in next_results_. // name, use the one in next_results_.
next_result_.args = next_result_.args.UnionWith(channel_args_); next_result_->args = next_result_->args.UnionWith(channel_args_);
result_handler_->ReportResult(std::move(next_result_)); result_handler_->ReportResult(std::move(*next_result_));
has_next_result_ = false; next_result_.reset();
} }
} }
void FakeResolver::ReturnReresolutionResult() {
reresolution_closure_pending_ = false;
MaybeSendResultLocked();
Unref();
}
class FakeResolverResponseSetter {
public:
explicit FakeResolverResponseSetter(RefCountedPtr<FakeResolver> resolver,
Resolver::Result result,
bool has_result = false,
bool immediate = true)
: resolver_(std::move(resolver)),
result_(std::move(result)),
has_result_(has_result),
immediate_(immediate) {}
void SetResponseLocked();
void SetReresolutionResponseLocked();
void SetFailureLocked();
private:
RefCountedPtr<FakeResolver> resolver_;
Resolver::Result result_;
bool has_result_;
bool immediate_;
};
// Deletes object when done
void FakeResolverResponseSetter::SetReresolutionResponseLocked() {
if (!resolver_->shutdown_) {
resolver_->reresolution_result_ = std::move(result_);
resolver_->has_reresolution_result_ = has_result_;
}
delete this;
}
// Deletes object when done
void FakeResolverResponseSetter::SetResponseLocked() {
if (!resolver_->shutdown_) {
resolver_->next_result_ = std::move(result_);
resolver_->has_next_result_ = true;
resolver_->MaybeSendResultLocked();
}
delete this;
}
// Deletes object when done
void FakeResolverResponseSetter::SetFailureLocked() {
if (!resolver_->shutdown_) {
resolver_->return_failure_ = true;
if (immediate_) resolver_->MaybeSendResultLocked();
}
delete this;
}
// //
// FakeResolverResponseGenerator // FakeResolverResponseGenerator
// //
@ -220,101 +133,73 @@ void FakeResolverResponseGenerator::SetResponseAndNotify(
{ {
MutexLock lock(&mu_); MutexLock lock(&mu_);
if (resolver_ == nullptr) { if (resolver_ == nullptr) {
has_result_ = true;
result_ = std::move(result); result_ = std::move(result);
if (notify_when_set != nullptr) notify_when_set->Notify(); if (notify_when_set != nullptr) notify_when_set->Notify();
return; return;
} }
resolver = resolver_->Ref(); resolver = resolver_->Ref();
} }
FakeResolverResponseSetter* arg = SendResultToResolver(std::move(resolver), std::move(result), notify_when_set);
new FakeResolverResponseSetter(resolver, std::move(result));
resolver->work_serializer_->Run(
[arg, notify_when_set]() {
arg->SetResponseLocked();
if (notify_when_set != nullptr) notify_when_set->Notify();
},
DEBUG_LOCATION);
} }
void FakeResolverResponseGenerator::SetReresolutionResponseAndNotify( void FakeResolverResponseGenerator::SetFakeResolver(
Resolver::Result result, Notification* notify_when_set) { RefCountedPtr<FakeResolver> resolver) {
RefCountedPtr<FakeResolver> resolver; Resolver::Result result;
{ {
MutexLock lock(&mu_); MutexLock lock(&mu_);
GPR_ASSERT(resolver_ != nullptr); resolver_ = resolver;
resolver = resolver_->Ref(); if (resolver_set_cv_ != nullptr) resolver_set_cv_->SignalAll();
if (resolver == nullptr) return;
if (!result_.has_value()) return;
result = std::move(*result_);
result_.reset();
} }
FakeResolverResponseSetter* arg = new FakeResolverResponseSetter( SendResultToResolver(std::move(resolver), std::move(result), nullptr);
resolver, std::move(result), true /* has_result */); }
resolver->work_serializer_->Run(
[arg, notify_when_set]() { void FakeResolverResponseGenerator::SendResultToResolver(
arg->SetReresolutionResponseLocked(); RefCountedPtr<FakeResolver> resolver, Resolver::Result result,
Notification* notify_when_set) {
auto* resolver_ptr = resolver.get();
resolver_ptr->work_serializer_->Run(
[resolver = std::move(resolver), result = std::move(result),
notify_when_set]() mutable {
if (!resolver->shutdown_) {
resolver->next_result_ = std::move(result);
resolver->MaybeSendResultLocked();
}
if (notify_when_set != nullptr) notify_when_set->Notify(); if (notify_when_set != nullptr) notify_when_set->Notify();
}, },
DEBUG_LOCATION); DEBUG_LOCATION);
} }
void FakeResolverResponseGenerator::UnsetReresolutionResponse() { bool FakeResolverResponseGenerator::WaitForResolverSet(absl::Duration timeout) {
RefCountedPtr<FakeResolver> resolver; MutexLock lock(&mu_);
{ if (resolver_ == nullptr) {
MutexLock lock(&mu_); CondVar condition;
GPR_ASSERT(resolver_ != nullptr); resolver_set_cv_ = &condition;
resolver = resolver_->Ref(); condition.WaitWithTimeout(&mu_, timeout);
} resolver_set_cv_ = nullptr;
FakeResolverResponseSetter* arg =
new FakeResolverResponseSetter(resolver, Resolver::Result());
resolver->work_serializer_->Run(
[arg]() { arg->SetReresolutionResponseLocked(); }, DEBUG_LOCATION);
}
void FakeResolverResponseGenerator::SetFailure() {
RefCountedPtr<FakeResolver> resolver;
{
MutexLock lock(&mu_);
GPR_ASSERT(resolver_ != nullptr);
resolver = resolver_->Ref();
}
FakeResolverResponseSetter* arg =
new FakeResolverResponseSetter(resolver, Resolver::Result());
resolver->work_serializer_->Run([arg]() { arg->SetFailureLocked(); },
DEBUG_LOCATION);
}
void FakeResolverResponseGenerator::SetFailureOnReresolution() {
RefCountedPtr<FakeResolver> resolver;
{
MutexLock lock(&mu_);
GPR_ASSERT(resolver_ != nullptr);
resolver = resolver_->Ref();
} }
FakeResolverResponseSetter* arg = new FakeResolverResponseSetter( return resolver_ != nullptr;
resolver, Resolver::Result(), false /* has_result */,
false /* immediate */);
resolver->work_serializer_->Run([arg]() { arg->SetFailureLocked(); },
DEBUG_LOCATION);
} }
void FakeResolverResponseGenerator::SetFakeResolver( bool FakeResolverResponseGenerator::WaitForReresolutionRequest(
RefCountedPtr<FakeResolver> resolver) { absl::Duration timeout) {
MutexLock lock(&mu_); MutexLock lock(&reresolution_mu_);
resolver_ = std::move(resolver); if (!reresolution_requested_) {
cv_.SignalAll(); CondVar condition;
if (resolver_ == nullptr) return; reresolution_cv_ = &condition;
if (has_result_) { condition.WaitWithTimeout(&reresolution_mu_, timeout);
FakeResolverResponseSetter* arg = reresolution_cv_ = nullptr;
new FakeResolverResponseSetter(resolver_, std::move(result_));
resolver_->work_serializer_->Run([arg]() { arg->SetResponseLocked(); },
DEBUG_LOCATION);
has_result_ = false;
} }
return std::exchange(reresolution_requested_, false);
} }
void FakeResolverResponseGenerator::WaitForResolverSet() { void FakeResolverResponseGenerator::ReresolutionRequested() {
MutexLock lock(&mu_); MutexLock lock(&reresolution_mu_);
while (resolver_ == nullptr) { reresolution_requested_ = true;
cv_.Wait(&mu_); if (reresolution_cv_ != nullptr) reresolution_cv_->SignalAll();
}
} }
namespace { namespace {
@ -341,22 +226,6 @@ const grpc_arg_pointer_vtable
ResponseGeneratorChannelArgCopy, ResponseGeneratorChannelArgDestroy, ResponseGeneratorChannelArgCopy, ResponseGeneratorChannelArgDestroy,
ResponseGeneratorChannelArgCmp}; ResponseGeneratorChannelArgCmp};
grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
FakeResolverResponseGenerator* generator) {
return grpc_channel_arg_pointer_create(
const_cast<char*>(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR), generator,
&kChannelArgPointerVtable);
}
RefCountedPtr<FakeResolverResponseGenerator>
FakeResolverResponseGenerator::GetFromArgs(const grpc_channel_args* args) {
auto* response_generator =
grpc_channel_args_find_pointer<FakeResolverResponseGenerator>(
args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
if (response_generator == nullptr) return nullptr;
return response_generator->Ref();
}
// //
// Factory // Factory
// //

@ -23,6 +23,8 @@
#include "absl/base/thread_annotations.h" #include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/optional.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
@ -42,8 +44,7 @@ class FakeResolver;
/// A mechanism for generating responses for the fake resolver. /// A mechanism for generating responses for the fake resolver.
/// An instance of this class is passed to the fake resolver via a channel /// An instance of this class is passed to the fake resolver via a channel
/// argument (see \a MakeChannelArg()) and used to inject and trigger custom /// argument and used to inject and trigger custom resolutions.
/// resolutions.
// TODO(roth): I would ideally like this to be InternallyRefCounted // TODO(roth): I would ideally like this to be InternallyRefCounted
// instead of RefCounted, but external refs are currently needed to // instead of RefCounted, but external refs are currently needed to
// encode this in channel args. Once channel_args are converted to C++, // encode this in channel args. Once channel_args are converted to C++,
@ -77,50 +78,20 @@ class FakeResolverResponseGenerator
n.WaitForNotification(); n.WaitForNotification();
} }
// Sets the re-resolution response, which is returned by the fake resolver // Waits up to timeout for a re-resolution request. Returns true if a
// when re-resolution is requested (via \a RequestReresolutionLocked()). // re-resolution request is seen, or false if timeout occurs. Returns
// The new re-resolution response replaces any previous re-resolution // true immediately if there was a re-resolution request since the
// response that may have been set by a previous call. // last time this method was called.
// notify_when_set is an optional notification to signal when the response has bool WaitForReresolutionRequest(absl::Duration timeout);
// been set.
void SetReresolutionResponseAndNotify(Resolver::Result result,
Notification* notify_when_set);
void SetReresolutionResponseAsync(Resolver::Result result) {
SetReresolutionResponseAndNotify(std::move(result), nullptr);
}
void SetReresolutionResponseSynchronously(Resolver::Result result) {
Notification n;
SetReresolutionResponseAndNotify(std::move(result), &n);
n.WaitForNotification();
}
// Unsets the re-resolution response. After this, the fake resolver will
// not return anything when \a RequestReresolutionLocked() is called.
void UnsetReresolutionResponse();
// Tells the resolver to return a transient failure.
void SetFailure();
// Same as SetFailure(), but instead of returning the error
// immediately, waits for the next call to RequestReresolutionLocked().
void SetFailureOnReresolution();
// Returns a channel arg containing \a generator.
// TODO(roth): When we have time, make this a non-static method.
static grpc_arg MakeChannelArg(FakeResolverResponseGenerator* generator);
// Returns the response generator in \a args, or null if not found. // Wait for a resolver to be set (setting may be happening asynchronously, so
static RefCountedPtr<FakeResolverResponseGenerator> GetFromArgs( // this may block - consider it test only).
const grpc_channel_args* args); bool WaitForResolverSet(absl::Duration timeout);
static absl::string_view ChannelArgName() { static absl::string_view ChannelArgName() {
return GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR; return GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
} }
// Wait for a resolver to be set (setting may be happening asynchronously, so
// this may block - consider it test only).
void WaitForResolverSet();
static int ChannelArgsCompare(const FakeResolverResponseGenerator* a, static int ChannelArgsCompare(const FakeResolverResponseGenerator* a,
const FakeResolverResponseGenerator* b) { const FakeResolverResponseGenerator* b) {
return QsortCompare(a, b); return QsortCompare(a, b);
@ -128,15 +99,29 @@ class FakeResolverResponseGenerator
private: private:
friend class FakeResolver; friend class FakeResolver;
// Set the corresponding FakeResolver to this generator. // Set the corresponding FakeResolver to this generator.
void SetFakeResolver(RefCountedPtr<FakeResolver> resolver); void SetFakeResolver(RefCountedPtr<FakeResolver> resolver);
// Called by FakeResolver when re-resolution is requested.
void ReresolutionRequested();
// Helper function to send a result to the resolver.
static void SendResultToResolver(RefCountedPtr<FakeResolver> resolver,
Resolver::Result result,
Notification* notify_when_set);
// Mutex protecting the members below. // Mutex protecting the members below.
Mutex mu_; Mutex mu_;
CondVar cv_; CondVar* resolver_set_cv_ ABSL_GUARDED_BY(mu_) = nullptr;
RefCountedPtr<FakeResolver> resolver_ ABSL_GUARDED_BY(mu_); RefCountedPtr<FakeResolver> resolver_ ABSL_GUARDED_BY(mu_);
Resolver::Result result_ ABSL_GUARDED_BY(mu_); // Temporarily stores the result when it gets set before the response
bool has_result_ ABSL_GUARDED_BY(mu_) = false; // generator is seen by the FakeResolver.
absl::optional<Resolver::Result> result_ ABSL_GUARDED_BY(mu_);
Mutex reresolution_mu_;
CondVar* reresolution_cv_ ABSL_GUARDED_BY(reresolution_mu_) = nullptr;
bool reresolution_requested_ ABSL_GUARDED_BY(reresolution_mu_) = false;
}; };
} // namespace grpc_core } // namespace grpc_core

@ -143,6 +143,7 @@ const RetryMethodConfig* RetryFilter::GetRetryPolicy(
const grpc_channel_filter RetryFilter::kVtable = { const grpc_channel_filter RetryFilter::kVtable = {
RetryFilter::LegacyCallData::StartTransportStreamOpBatch, RetryFilter::LegacyCallData::StartTransportStreamOpBatch,
nullptr, nullptr,
/* init_call: */ nullptr,
RetryFilter::StartTransportOp, RetryFilter::StartTransportOp,
sizeof(RetryFilter::LegacyCallData), sizeof(RetryFilter::LegacyCallData),
RetryFilter::LegacyCallData::Init, RetryFilter::LegacyCallData::Init,

@ -343,6 +343,7 @@ const grpc_channel_filter grpc_client_deadline_filter = {
grpc_core::NextPromiseFactory next_promise_factory) { grpc_core::NextPromiseFactory next_promise_factory) {
return next_promise_factory(std::move(call_args)); return next_promise_factory(std::move(call_args));
}, },
/* init_call: */ nullptr,
grpc_channel_next_op, grpc_channel_next_op,
sizeof(grpc_deadline_state), sizeof(grpc_deadline_state),
deadline_init_call_elem, deadline_init_call_elem,
@ -368,6 +369,17 @@ const grpc_channel_filter grpc_server_deadline_filter = {
} }
return next_promise_factory(std::move(call_args)); return next_promise_factory(std::move(call_args));
}, },
[](grpc_channel_element*, grpc_core::CallSpineInterface* spine) {
spine->client_initial_metadata().receiver.InterceptAndMap(
[](grpc_core::ClientMetadataHandle md) {
auto deadline = md->get(grpc_core::GrpcTimeoutMetadata());
if (deadline.has_value()) {
grpc_core::GetContext<grpc_core::CallContext>()->UpdateDeadline(
*deadline);
}
return md;
});
},
grpc_channel_next_op, grpc_channel_next_op,
sizeof(server_call_data), sizeof(server_call_data),
deadline_init_call_elem, deadline_init_call_elem,

@ -51,6 +51,10 @@
namespace grpc_core { namespace grpc_core {
const NoInterceptor HttpClientFilter::Call::OnServerToClientMessage;
const NoInterceptor HttpClientFilter::Call::OnClientToServerMessage;
const NoInterceptor HttpClientFilter::Call::OnFinalize;
const grpc_channel_filter HttpClientFilter::kFilter = const grpc_channel_filter HttpClientFilter::kFilter =
MakePromiseBasedFilter<HttpClientFilter, FilterEndpoint::kClient, MakePromiseBasedFilter<HttpClientFilter, FilterEndpoint::kClient,
kFilterExaminesServerInitialMetadata>("http-client"); kFilterExaminesServerInitialMetadata>("http-client");
@ -105,40 +109,27 @@ Slice UserAgentFromArgs(const ChannelArgs& args,
} }
} // namespace } // namespace
ArenaPromise<ServerMetadataHandle> HttpClientFilter::MakeCallPromise( void HttpClientFilter::Call::OnClientInitialMetadata(ClientMetadata& md,
CallArgs call_args, NextPromiseFactory next_promise_factory) { HttpClientFilter* filter) {
auto& md = call_args.client_initial_metadata; if (filter->test_only_use_put_requests_) {
if (test_only_use_put_requests_) { md.Set(HttpMethodMetadata(), HttpMethodMetadata::kPut);
md->Set(HttpMethodMetadata(), HttpMethodMetadata::kPut);
} else { } else {
md->Set(HttpMethodMetadata(), HttpMethodMetadata::kPost); md.Set(HttpMethodMetadata(), HttpMethodMetadata::kPost);
} }
md->Set(HttpSchemeMetadata(), scheme_); md.Set(HttpSchemeMetadata(), filter->scheme_);
md->Set(TeMetadata(), TeMetadata::kTrailers); md.Set(TeMetadata(), TeMetadata::kTrailers);
md->Set(ContentTypeMetadata(), ContentTypeMetadata::kApplicationGrpc); md.Set(ContentTypeMetadata(), ContentTypeMetadata::kApplicationGrpc);
md->Set(UserAgentMetadata(), user_agent_.Ref()); md.Set(UserAgentMetadata(), filter->user_agent_.Ref());
}
auto* initial_metadata_err =
GetContext<Arena>()->New<Latch<ServerMetadataHandle>>(); absl::Status HttpClientFilter::Call::OnServerInitialMetadata(
ServerMetadata& md) {
call_args.server_initial_metadata->InterceptAndMap( return CheckServerMetadata(&md);
[initial_metadata_err]( }
ServerMetadataHandle md) -> absl::optional<ServerMetadataHandle> {
auto r = CheckServerMetadata(md.get()); absl::Status HttpClientFilter::Call::OnServerTrailingMetadata(
if (!r.ok()) { ServerMetadata& md) {
initial_metadata_err->Set(ServerMetadataFromStatus(r)); return CheckServerMetadata(&md);
return absl::nullopt;
}
return std::move(md);
});
return Race(initial_metadata_err->Wait(),
Map(next_promise_factory(std::move(call_args)),
[](ServerMetadataHandle md) -> ServerMetadataHandle {
auto r = CheckServerMetadata(md.get());
if (!r.ok()) return ServerMetadataFromStatus(r);
return md;
}));
} }
HttpClientFilter::HttpClientFilter(HttpSchemeMetadata::ValueType scheme, HttpClientFilter::HttpClientFilter(HttpSchemeMetadata::ValueType scheme,

@ -25,23 +25,28 @@
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/promise_based_filter.h" #include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/slice/slice.h" #include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
namespace grpc_core { namespace grpc_core {
class HttpClientFilter : public ChannelFilter { class HttpClientFilter : public ImplementChannelFilter<HttpClientFilter> {
public: public:
static const grpc_channel_filter kFilter; static const grpc_channel_filter kFilter;
static absl::StatusOr<HttpClientFilter> Create( static absl::StatusOr<HttpClientFilter> Create(
const ChannelArgs& args, ChannelFilter::Args filter_args); const ChannelArgs& args, ChannelFilter::Args filter_args);
// Construct a promise for one call. class Call {
ArenaPromise<ServerMetadataHandle> MakeCallPromise( public:
CallArgs call_args, NextPromiseFactory next_promise_factory) override; void OnClientInitialMetadata(ClientMetadata& md, HttpClientFilter* filter);
absl::Status OnServerInitialMetadata(ServerMetadata& md);
absl::Status OnServerTrailingMetadata(ServerMetadata& md);
static const NoInterceptor OnClientToServerMessage;
static const NoInterceptor OnServerToClientMessage;
static const NoInterceptor OnFinalize;
};
private: private:
HttpClientFilter(HttpSchemeMetadata::ValueType scheme, Slice user_agent, HttpClientFilter(HttpSchemeMetadata::ValueType scheme, Slice user_agent,

@ -49,6 +49,10 @@
namespace grpc_core { namespace grpc_core {
const NoInterceptor HttpServerFilter::Call::OnClientToServerMessage;
const NoInterceptor HttpServerFilter::Call::OnServerToClientMessage;
const NoInterceptor HttpServerFilter::Call::OnFinalize;
const grpc_channel_filter HttpServerFilter::kFilter = const grpc_channel_filter HttpServerFilter::kFilter =
MakePromiseBasedFilter<HttpServerFilter, FilterEndpoint::kServer, MakePromiseBasedFilter<HttpServerFilter, FilterEndpoint::kServer,
kFilterExaminesServerInitialMetadata>("http-server"); kFilterExaminesServerInitialMetadata>("http-server");
@ -71,85 +75,81 @@ ServerMetadataHandle MalformedRequest(absl::string_view explanation) {
} }
} // namespace } // namespace
ArenaPromise<ServerMetadataHandle> HttpServerFilter::MakeCallPromise( ServerMetadataHandle HttpServerFilter::Call::OnClientInitialMetadata(
CallArgs call_args, NextPromiseFactory next_promise_factory) { ClientMetadata& md, HttpServerFilter* filter) {
const auto& md = call_args.client_initial_metadata; auto method = md.get(HttpMethodMetadata());
auto method = md->get(HttpMethodMetadata());
if (method.has_value()) { if (method.has_value()) {
switch (*method) { switch (*method) {
case HttpMethodMetadata::kPost: case HttpMethodMetadata::kPost:
break; break;
case HttpMethodMetadata::kPut: case HttpMethodMetadata::kPut:
if (allow_put_requests_) { if (filter->allow_put_requests_) {
break; break;
} }
ABSL_FALLTHROUGH_INTENDED; ABSL_FALLTHROUGH_INTENDED;
case HttpMethodMetadata::kInvalid: case HttpMethodMetadata::kInvalid:
case HttpMethodMetadata::kGet: case HttpMethodMetadata::kGet:
return Immediate(MalformedRequest("Bad method header")); return MalformedRequest("Bad method header");
} }
} else { } else {
return Immediate(MalformedRequest("Missing :method header")); return MalformedRequest("Missing :method header");
} }
auto te = md->Take(TeMetadata()); auto te = md.Take(TeMetadata());
if (te == TeMetadata::kTrailers) { if (te == TeMetadata::kTrailers) {
// Do nothing, ok. // Do nothing, ok.
} else if (!te.has_value()) { } else if (!te.has_value()) {
return Immediate(MalformedRequest("Missing :te header")); return MalformedRequest("Missing :te header");
} else { } else {
return Immediate(MalformedRequest("Bad :te header")); return MalformedRequest("Bad :te header");
} }
auto scheme = md->Take(HttpSchemeMetadata()); auto scheme = md.Take(HttpSchemeMetadata());
if (scheme.has_value()) { if (scheme.has_value()) {
if (*scheme == HttpSchemeMetadata::kInvalid) { if (*scheme == HttpSchemeMetadata::kInvalid) {
return Immediate(MalformedRequest("Bad :scheme header")); return MalformedRequest("Bad :scheme header");
} }
} else { } else {
return Immediate(MalformedRequest("Missing :scheme header")); return MalformedRequest("Missing :scheme header");
} }
md->Remove(ContentTypeMetadata()); md.Remove(ContentTypeMetadata());
Slice* path_slice = md->get_pointer(HttpPathMetadata()); Slice* path_slice = md.get_pointer(HttpPathMetadata());
if (path_slice == nullptr) { if (path_slice == nullptr) {
return Immediate(MalformedRequest("Missing :path header")); return MalformedRequest("Missing :path header");
} }
if (md->get_pointer(HttpAuthorityMetadata()) == nullptr) { if (md.get_pointer(HttpAuthorityMetadata()) == nullptr) {
absl::optional<Slice> host = md->Take(HostMetadata()); absl::optional<Slice> host = md.Take(HostMetadata());
if (host.has_value()) { if (host.has_value()) {
md->Set(HttpAuthorityMetadata(), std::move(*host)); md.Set(HttpAuthorityMetadata(), std::move(*host));
} }
} }
if (md->get_pointer(HttpAuthorityMetadata()) == nullptr) { if (md.get_pointer(HttpAuthorityMetadata()) == nullptr) {
return Immediate(MalformedRequest("Missing :authority header")); return MalformedRequest("Missing :authority header");
} }
if (!surface_user_agent_) { if (!filter->surface_user_agent_) {
md->Remove(UserAgentMetadata()); md.Remove(UserAgentMetadata());
} }
call_args.server_initial_metadata->InterceptAndMap( return nullptr;
[](ServerMetadataHandle md) { }
if (grpc_call_trace.enabled()) {
gpr_log(GPR_INFO, "%s[http-server] Write metadata", void HttpServerFilter::Call::OnServerInitialMetadata(ServerMetadata& md) {
Activity::current()->DebugTag().c_str()); if (grpc_call_trace.enabled()) {
} gpr_log(GPR_INFO, "%s[http-server] Write metadata",
FilterOutgoingMetadata(md.get()); Activity::current()->DebugTag().c_str());
md->Set(HttpStatusMetadata(), 200); }
md->Set(ContentTypeMetadata(), ContentTypeMetadata::kApplicationGrpc); FilterOutgoingMetadata(&md);
return md; md.Set(HttpStatusMetadata(), 200);
}); md.Set(ContentTypeMetadata(), ContentTypeMetadata::kApplicationGrpc);
}
return Map(next_promise_factory(std::move(call_args)),
[](ServerMetadataHandle md) -> ServerMetadataHandle { void HttpServerFilter::Call::OnServerTrailingMetadata(ServerMetadata& md) {
FilterOutgoingMetadata(md.get()); FilterOutgoingMetadata(&md);
return md;
});
} }
absl::StatusOr<HttpServerFilter> HttpServerFilter::Create( absl::StatusOr<HttpServerFilter> HttpServerFilter::Create(

@ -32,16 +32,23 @@
namespace grpc_core { namespace grpc_core {
// Processes metadata on the server side for HTTP2 transports // Processes metadata on the server side for HTTP2 transports
class HttpServerFilter : public ChannelFilter { class HttpServerFilter : public ImplementChannelFilter<HttpServerFilter> {
public: public:
static const grpc_channel_filter kFilter; static const grpc_channel_filter kFilter;
static absl::StatusOr<HttpServerFilter> Create( static absl::StatusOr<HttpServerFilter> Create(
const ChannelArgs& args, ChannelFilter::Args filter_args); const ChannelArgs& args, ChannelFilter::Args filter_args);
// Construct a promise for one call. class Call {
ArenaPromise<ServerMetadataHandle> MakeCallPromise( public:
CallArgs call_args, NextPromiseFactory next_promise_factory) override; ServerMetadataHandle OnClientInitialMetadata(ClientMetadata& md,
HttpServerFilter* filter);
void OnServerInitialMetadata(ServerMetadata& md);
void OnServerTrailingMetadata(ServerMetadata& md);
static const NoInterceptor OnClientToServerMessage;
static const NoInterceptor OnServerToClientMessage;
static const NoInterceptor OnFinalize;
};
private: private:
HttpServerFilter(bool surface_user_agent, bool allow_put_requests) HttpServerFilter(bool surface_user_agent, bool allow_put_requests)

@ -50,6 +50,15 @@
namespace grpc_core { namespace grpc_core {
const NoInterceptor ClientMessageSizeFilter::Call::OnClientInitialMetadata;
const NoInterceptor ClientMessageSizeFilter::Call::OnServerInitialMetadata;
const NoInterceptor ClientMessageSizeFilter::Call::OnServerTrailingMetadata;
const NoInterceptor ClientMessageSizeFilter::Call::OnFinalize;
const NoInterceptor ServerMessageSizeFilter::Call::OnClientInitialMetadata;
const NoInterceptor ServerMessageSizeFilter::Call::OnServerInitialMetadata;
const NoInterceptor ServerMessageSizeFilter::Call::OnServerTrailingMetadata;
const NoInterceptor ServerMessageSizeFilter::Call::OnFinalize;
// //
// MessageSizeParsedConfig // MessageSizeParsedConfig
// //
@ -138,60 +147,6 @@ const grpc_channel_filter ServerMessageSizeFilter::kFilter =
kFilterExaminesOutboundMessages | kFilterExaminesOutboundMessages |
kFilterExaminesInboundMessages>("message_size"); kFilterExaminesInboundMessages>("message_size");
class MessageSizeFilter::CallBuilder {
private:
auto Interceptor(uint32_t max_length, bool is_send) {
return [max_length, is_send,
err = err_](MessageHandle msg) -> absl::optional<MessageHandle> {
if (grpc_call_trace.enabled()) {
gpr_log(GPR_INFO, "%s[message_size] %s len:%" PRIdPTR " max:%d",
Activity::current()->DebugTag().c_str(),
is_send ? "send" : "recv", msg->payload()->Length(),
max_length);
}
if (msg->payload()->Length() > max_length) {
if (err->is_set()) return std::move(msg);
auto r = GetContext<Arena>()->MakePooled<ServerMetadata>(
GetContext<Arena>());
r->Set(GrpcStatusMetadata(), GRPC_STATUS_RESOURCE_EXHAUSTED);
r->Set(GrpcMessageMetadata(),
Slice::FromCopiedString(
absl::StrFormat("%s message larger than max (%u vs. %d)",
is_send ? "Sent" : "Received",
msg->payload()->Length(), max_length)));
err->Set(std::move(r));
return absl::nullopt;
}
return std::move(msg);
};
}
public:
explicit CallBuilder(const MessageSizeParsedConfig& limits)
: limits_(limits) {}
template <typename T>
void AddSend(T* pipe_end) {
if (!limits_.max_send_size().has_value()) return;
pipe_end->InterceptAndMap(Interceptor(*limits_.max_send_size(), true));
}
template <typename T>
void AddRecv(T* pipe_end) {
if (!limits_.max_recv_size().has_value()) return;
pipe_end->InterceptAndMap(Interceptor(*limits_.max_recv_size(), false));
}
ArenaPromise<ServerMetadataHandle> Run(
CallArgs call_args, NextPromiseFactory next_promise_factory) {
return Race(err_->Wait(), next_promise_factory(std::move(call_args)));
}
private:
Latch<ServerMetadataHandle>* const err_ =
GetContext<Arena>()->ManagedNew<Latch<ServerMetadataHandle>>();
MessageSizeParsedConfig limits_;
};
absl::StatusOr<ClientMessageSizeFilter> ClientMessageSizeFilter::Create( absl::StatusOr<ClientMessageSizeFilter> ClientMessageSizeFilter::Create(
const ChannelArgs& args, ChannelFilter::Args) { const ChannelArgs& args, ChannelFilter::Args) {
return ClientMessageSizeFilter(args); return ClientMessageSizeFilter(args);
@ -202,20 +157,40 @@ absl::StatusOr<ServerMessageSizeFilter> ServerMessageSizeFilter::Create(
return ServerMessageSizeFilter(args); return ServerMessageSizeFilter(args);
} }
ArenaPromise<ServerMetadataHandle> ClientMessageSizeFilter::MakeCallPromise( namespace {
CallArgs call_args, NextPromiseFactory next_promise_factory) { ServerMetadataHandle CheckPayload(const Message& msg,
absl::optional<uint32_t> max_length,
bool is_send) {
if (!max_length.has_value()) return nullptr;
if (GRPC_TRACE_FLAG_ENABLED(grpc_call_trace)) {
gpr_log(GPR_INFO, "%s[message_size] %s len:%" PRIdPTR " max:%d",
Activity::current()->DebugTag().c_str(), is_send ? "send" : "recv",
msg.payload()->Length(), *max_length);
}
if (msg.payload()->Length() <= *max_length) return nullptr;
auto r = GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
r->Set(GrpcStatusMetadata(), GRPC_STATUS_RESOURCE_EXHAUSTED);
r->Set(GrpcMessageMetadata(), Slice::FromCopiedString(absl::StrFormat(
"%s message larger than max (%u vs. %d)",
is_send ? "Sent" : "Received",
msg.payload()->Length(), *max_length)));
return r;
}
} // namespace
ClientMessageSizeFilter::Call::Call(ClientMessageSizeFilter* filter)
: limits_(filter->parsed_config_) {
// Get max sizes from channel data, then merge in per-method config values. // Get max sizes from channel data, then merge in per-method config values.
// Note: Per-method config is only available on the client, so we // Note: Per-method config is only available on the client, so we
// apply the max request size to the send limit and the max response // apply the max request size to the send limit and the max response
// size to the receive limit. // size to the receive limit.
MessageSizeParsedConfig limits = this->limits();
const MessageSizeParsedConfig* config_from_call_context = const MessageSizeParsedConfig* config_from_call_context =
MessageSizeParsedConfig::GetFromCallContext( MessageSizeParsedConfig::GetFromCallContext(
GetContext<grpc_call_context_element>(), GetContext<grpc_call_context_element>(),
service_config_parser_index_); filter->service_config_parser_index_);
if (config_from_call_context != nullptr) { if (config_from_call_context != nullptr) {
absl::optional<uint32_t> max_send_size = limits.max_send_size(); absl::optional<uint32_t> max_send_size = limits_.max_send_size();
absl::optional<uint32_t> max_recv_size = limits.max_recv_size(); absl::optional<uint32_t> max_recv_size = limits_.max_recv_size();
if (config_from_call_context->max_send_size().has_value() && if (config_from_call_context->max_send_size().has_value() &&
(!max_send_size.has_value() || (!max_send_size.has_value() ||
*config_from_call_context->max_send_size() < *max_send_size)) { *config_from_call_context->max_send_size() < *max_send_size)) {
@ -226,21 +201,28 @@ ArenaPromise<ServerMetadataHandle> ClientMessageSizeFilter::MakeCallPromise(
*config_from_call_context->max_recv_size() < *max_recv_size)) { *config_from_call_context->max_recv_size() < *max_recv_size)) {
max_recv_size = *config_from_call_context->max_recv_size(); max_recv_size = *config_from_call_context->max_recv_size();
} }
limits = MessageSizeParsedConfig(max_send_size, max_recv_size); limits_ = MessageSizeParsedConfig(max_send_size, max_recv_size);
} }
}
ServerMetadataHandle ServerMessageSizeFilter::Call::OnClientToServerMessage(
const Message& message, ServerMessageSizeFilter* filter) {
return CheckPayload(message, filter->parsed_config_.max_recv_size(), false);
}
ServerMetadataHandle ServerMessageSizeFilter::Call::OnServerToClientMessage(
const Message& message, ServerMessageSizeFilter* filter) {
return CheckPayload(message, filter->parsed_config_.max_send_size(), true);
}
CallBuilder b(limits); ServerMetadataHandle ClientMessageSizeFilter::Call::OnClientToServerMessage(
b.AddSend(call_args.client_to_server_messages); const Message& message) {
b.AddRecv(call_args.server_to_client_messages); return CheckPayload(message, limits_.max_send_size(), true);
return b.Run(std::move(call_args), std::move(next_promise_factory));
} }
ArenaPromise<ServerMetadataHandle> ServerMessageSizeFilter::MakeCallPromise( ServerMetadataHandle ClientMessageSizeFilter::Call::OnServerToClientMessage(
CallArgs call_args, NextPromiseFactory next_promise_factory) { const Message& message) {
CallBuilder b(limits()); return CheckPayload(message, limits_.max_recv_size(), false);
b.AddSend(call_args.server_to_client_messages);
b.AddRecv(call_args.client_to_server_messages);
return b.Run(std::move(call_args), std::move(next_promise_factory));
} }
namespace { namespace {

@ -86,48 +86,60 @@ class MessageSizeParser : public ServiceConfigParser::Parser {
absl::optional<uint32_t> GetMaxRecvSizeFromChannelArgs(const ChannelArgs& args); absl::optional<uint32_t> GetMaxRecvSizeFromChannelArgs(const ChannelArgs& args);
absl::optional<uint32_t> GetMaxSendSizeFromChannelArgs(const ChannelArgs& args); absl::optional<uint32_t> GetMaxSendSizeFromChannelArgs(const ChannelArgs& args);
class MessageSizeFilter : public ChannelFilter { class ServerMessageSizeFilter final
protected: : public ImplementChannelFilter<ServerMessageSizeFilter> {
explicit MessageSizeFilter(const ChannelArgs& args)
: limits_(MessageSizeParsedConfig::GetFromChannelArgs(args)) {}
class CallBuilder;
const MessageSizeParsedConfig& limits() const { return limits_; }
private:
MessageSizeParsedConfig limits_;
};
class ServerMessageSizeFilter final : public MessageSizeFilter {
public: public:
static const grpc_channel_filter kFilter; static const grpc_channel_filter kFilter;
static absl::StatusOr<ServerMessageSizeFilter> Create( static absl::StatusOr<ServerMessageSizeFilter> Create(
const ChannelArgs& args, ChannelFilter::Args filter_args); const ChannelArgs& args, ChannelFilter::Args filter_args);
// Construct a promise for one call. class Call {
ArenaPromise<ServerMetadataHandle> MakeCallPromise( public:
CallArgs call_args, NextPromiseFactory next_promise_factory) override; static const NoInterceptor OnClientInitialMetadata;
static const NoInterceptor OnServerInitialMetadata;
static const NoInterceptor OnServerTrailingMetadata;
static const NoInterceptor OnFinalize;
ServerMetadataHandle OnClientToServerMessage(
const Message& message, ServerMessageSizeFilter* filter);
ServerMetadataHandle OnServerToClientMessage(
const Message& message, ServerMessageSizeFilter* filter);
};
private: private:
using MessageSizeFilter::MessageSizeFilter; explicit ServerMessageSizeFilter(const ChannelArgs& args)
: parsed_config_(MessageSizeParsedConfig::GetFromChannelArgs(args)) {}
const MessageSizeParsedConfig parsed_config_;
}; };
class ClientMessageSizeFilter final : public MessageSizeFilter { class ClientMessageSizeFilter final
: public ImplementChannelFilter<ClientMessageSizeFilter> {
public: public:
static const grpc_channel_filter kFilter; static const grpc_channel_filter kFilter;
static absl::StatusOr<ClientMessageSizeFilter> Create( static absl::StatusOr<ClientMessageSizeFilter> Create(
const ChannelArgs& args, ChannelFilter::Args filter_args); const ChannelArgs& args, ChannelFilter::Args filter_args);
// Construct a promise for one call. class Call {
ArenaPromise<ServerMetadataHandle> MakeCallPromise( public:
CallArgs call_args, NextPromiseFactory next_promise_factory) override; explicit Call(ClientMessageSizeFilter* filter);
static const NoInterceptor OnClientInitialMetadata;
static const NoInterceptor OnServerInitialMetadata;
static const NoInterceptor OnServerTrailingMetadata;
static const NoInterceptor OnFinalize;
ServerMetadataHandle OnClientToServerMessage(const Message& message);
ServerMetadataHandle OnServerToClientMessage(const Message& message);
private:
MessageSizeParsedConfig limits_;
};
private: private:
explicit ClientMessageSizeFilter(const ChannelArgs& args)
: parsed_config_(MessageSizeParsedConfig::GetFromChannelArgs(args)) {}
const size_t service_config_parser_index_{MessageSizeParser::ParserIndex()}; const size_t service_config_parser_index_{MessageSizeParser::ParserIndex()};
using MessageSizeFilter::MessageSizeFilter; const MessageSizeParsedConfig parsed_config_;
}; };
} // namespace grpc_core } // namespace grpc_core

@ -20,17 +20,26 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
#include "absl/random/bit_gen_ref.h"
#include "absl/random/random.h"
#include "absl/status/statusor.h"
#include <grpc/event_engine/event_engine.h> #include <grpc/event_engine/event_engine.h>
#include <grpc/slice.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/ext/transport/chaotic_good/frame.h" #include "src/core/ext/transport/chaotic_good/frame.h"
#include "src/core/ext/transport/chaotic_good/frame_header.h" #include "src/core/ext/transport/chaotic_good/frame_header.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/lib/gprpp/match.h" #include "src/core/lib/gprpp/match.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/activity.h" #include "src/core/lib/promise/activity.h"
#include "src/core/lib/promise/event_engine_wakeup_scheduler.h" #include "src/core/lib/promise/event_engine_wakeup_scheduler.h"
#include "src/core/lib/promise/join.h"
#include "src/core/lib/promise/loop.h" #include "src/core/lib/promise/loop.h"
#include "src/core/lib/promise/try_join.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/slice/slice.h" #include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h" #include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
@ -49,9 +58,15 @@ ClientTransport::ClientTransport(
control_endpoint_write_buffer_(SliceBuffer()), control_endpoint_write_buffer_(SliceBuffer()),
data_endpoint_write_buffer_(SliceBuffer()), data_endpoint_write_buffer_(SliceBuffer()),
hpack_compressor_(std::make_unique<HPackCompressor>()), hpack_compressor_(std::make_unique<HPackCompressor>()),
hpack_parser_(std::make_unique<HPackParser>()),
memory_allocator_(
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
"client_transport")),
arena_(MakeScopedArena(1024, &memory_allocator_)),
context_(arena_.get()),
event_engine_(event_engine) { event_engine_(event_engine) {
auto write_loop = Loop([this] { auto write_loop = Loop([this] {
return Seq( return TrySeq(
// Get next outgoing frame. // Get next outgoing frame.
this->outgoing_frames_.Next(), this->outgoing_frames_.Next(),
// Construct data buffers that will be sent to the endpoints. // Construct data buffers that will be sent to the endpoints.
@ -81,30 +96,93 @@ ClientTransport::ClientTransport(
}, },
// Write buffers to corresponding endpoints concurrently. // Write buffers to corresponding endpoints concurrently.
[this]() { [this]() {
return Join(this->control_endpoint_->Write( return TryJoin(
std::move(control_endpoint_write_buffer_)), control_endpoint_->Write(
this->data_endpoint_->Write( std::move(control_endpoint_write_buffer_)),
std::move(data_endpoint_write_buffer_))); data_endpoint_->Write(std::move(data_endpoint_write_buffer_)));
}, },
// Finish writes and return status. // Finish writes to difference endpoints and continue the loop.
[](std::tuple<absl::Status, absl::Status> ret) []() -> LoopCtl<absl::Status> {
-> LoopCtl<absl::Status> { // The write failures will be caught in TrySeq and exit loop.
// If writes failed, return failure status. // Therefore, only need to return Continue() in the last lambda
if (!(std::get<0>(ret).ok() || std::get<1>(ret).ok())) { // function.
// TODO(ladynana): handle the promise endpoint write failures with
// closing the transport.
return absl::InternalError("Promise endpoint writes failed.");
}
return Continue(); return Continue();
}); });
}); });
writer_ = MakeActivity( writer_ = MakeActivity(
// Continuously write next outgoing frames to promise endpoints. // Continuously write next outgoing frames to promise endpoints.
std::move(write_loop), EventEngineWakeupScheduler(event_engine_), std::move(write_loop), EventEngineWakeupScheduler(event_engine_),
[](absl::Status status) { [this](absl::Status status) {
GPR_ASSERT(status.code() == absl::StatusCode::kCancelled || if (!(status.ok() || status.code() == absl::StatusCode::kCancelled)) {
status.code() == absl::StatusCode::kInternal); this->AbortWithError();
}); }
},
// Hold Arena in activity for GetContext<Arena> usage.
arena_.get());
auto read_loop = Loop([this] {
return TrySeq(
// Read frame header from control endpoint.
// TODO(ladynana): remove memcpy in ReadSlice.
this->control_endpoint_->ReadSlice(FrameHeader::frame_header_size_),
// Read different parts of the server frame from control/data endpoints
// based on frame header.
[this](Slice read_buffer) mutable {
frame_header_ = std::make_shared<FrameHeader>(
FrameHeader::Parse(
reinterpret_cast<const uint8_t*>(
GRPC_SLICE_START_PTR(read_buffer.c_slice())))
.value());
// Read header and trailers from control endpoint.
// Read message padding and message from data endpoint.
return TryJoin(
control_endpoint_->Read(frame_header_->GetFrameLength()),
data_endpoint_->Read(frame_header_->message_padding +
frame_header_->message_length));
},
// Construct and send the server frame to corresponding stream.
[this](std::tuple<SliceBuffer, SliceBuffer> ret) mutable {
control_endpoint_read_buffer_ = std::move(std::get<0>(ret));
// Discard message padding and only keep message in data read buffer.
std::get<1>(ret).MoveLastNBytesIntoSliceBuffer(
frame_header_->message_length, data_endpoint_read_buffer_);
ServerFragmentFrame frame;
// Initialized to get this_cpu() info in global_stat().
ExecCtx exec_ctx;
// Deserialize frame from read buffer.
absl::BitGen bitgen;
auto status = frame.Deserialize(hpack_parser_.get(), *frame_header_,
absl::BitGenRef(bitgen),
control_endpoint_read_buffer_);
GPR_ASSERT(status.ok());
// Move message into frame.
frame.message = arena_->MakePooled<Message>(
std::move(data_endpoint_read_buffer_), 0);
auto stream_id = frame.frame_header.stream_id;
{
MutexLock lock(&mu_);
return stream_map_[stream_id]->Push(ServerFrame(std::move(frame)));
}
},
// Check if send frame to corresponding stream successfully.
[](bool ret) -> LoopCtl<absl::Status> {
if (ret) {
// Send incoming frames successfully.
return Continue();
} else {
return absl::InternalError("Send incoming frames failed.");
}
});
});
reader_ = MakeActivity(
// Continuously read next incoming frames from promise endpoints.
std::move(read_loop), EventEngineWakeupScheduler(event_engine_),
[this](absl::Status status) {
if (!(status.ok() || status.code() == absl::StatusCode::kCancelled)) {
this->AbortWithError();
}
},
// Hold Arena in activity for GetContext<Arena> usage.
arena_.get());
} }
} // namespace chaotic_good } // namespace chaotic_good

@ -17,29 +17,42 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <initializer_list> // IWYU pragma: keep #include <initializer_list> // IWYU pragma: keep
#include <map>
#include <memory> #include <memory>
#include <tuple>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "absl/base/thread_annotations.h" #include "absl/base/thread_annotations.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/types/optional.h"
#include "absl/types/variant.h" #include "absl/types/variant.h"
#include <grpc/event_engine/event_engine.h> #include <grpc/event_engine/event_engine.h>
#include <grpc/event_engine/memory_allocator.h>
#include "src/core/ext/transport/chaotic_good/frame.h" #include "src/core/ext/transport/chaotic_good/frame.h"
#include "src/core/ext/transport/chaotic_good/frame_header.h" #include "src/core/ext/transport/chaotic_good/frame_header.h"
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/promise/activity.h" #include "src/core/lib/promise/activity.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/for_each.h" #include "src/core/lib/promise/for_each.h"
#include "src/core/lib/promise/if.h"
#include "src/core/lib/promise/inter_activity_pipe.h"
#include "src/core/lib/promise/loop.h"
#include "src/core/lib/promise/mpsc.h" #include "src/core/lib/promise/mpsc.h"
#include "src/core/lib/promise/pipe.h" #include "src/core/lib/promise/pipe.h"
#include "src/core/lib/promise/seq.h" #include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/try_join.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/resource_quota/memory_quota.h"
#include "src/core/lib/slice/slice_buffer.h" #include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h" // IWYU pragma: keep #include "src/core/lib/transport/metadata_batch.h" // IWYU pragma: keep
#include "src/core/lib/transport/promise_endpoint.h" #include "src/core/lib/transport/promise_endpoint.h"
@ -58,18 +71,44 @@ class ClientTransport {
if (writer_ != nullptr) { if (writer_ != nullptr) {
writer_.reset(); writer_.reset();
} }
if (reader_ != nullptr) {
reader_.reset();
}
}
void AbortWithError() {
// Mark transport as unavailable when the endpoint write/read failed.
// Close all the available pipes.
if (!outgoing_frames_.IsClosed()) {
outgoing_frames_.MarkClosed();
}
MutexLock lock(&mu_);
for (const auto& pair : stream_map_) {
if (!pair.second->IsClose()) {
pair.second->MarkClose();
}
}
} }
auto AddStream(CallArgs call_args) { auto AddStream(CallArgs call_args) {
// At this point, the connection is set up. // At this point, the connection is set up.
// Start sending data frames. // Start sending data frames.
uint32_t stream_id; uint32_t stream_id;
InterActivityPipe<ServerFrame, server_frame_queue_size_> pipe_server_frames;
{ {
MutexLock lock(&mu_); MutexLock lock(&mu_);
stream_id = next_stream_id_++; stream_id = next_stream_id_++;
stream_map_.insert(
std::pair<uint32_t,
std::shared_ptr<InterActivityPipe<
ServerFrame, server_frame_queue_size_>::Sender>>(
stream_id, std::make_shared<InterActivityPipe<
ServerFrame, server_frame_queue_size_>::Sender>(
std::move(pipe_server_frames.sender))));
} }
return Seq( return TrySeq(
// Continuously send data frame with client to server messages. TryJoin(
ForEach(std::move(*call_args.client_to_server_messages), // Continuously send client frame with client to server messages.
ForEach(
std::move(*call_args.client_to_server_messages),
[stream_id, initial_frame = true, [stream_id, initial_frame = true,
client_initial_metadata = client_initial_metadata =
std::move(call_args.client_initial_metadata), std::move(call_args.client_initial_metadata),
@ -89,33 +128,112 @@ class ClientTransport {
frame.headers = std::move(client_initial_metadata); frame.headers = std::move(client_initial_metadata);
initial_frame = false; initial_frame = false;
} }
return Seq( return TrySeq(
outgoing_frames.Send(ClientFrame(std::move(frame))), outgoing_frames.Send(ClientFrame(std::move(frame))),
[](bool success) -> absl::Status { [](bool success) -> absl::Status {
if (!success) { if (!success) {
return absl::InternalError( // TODO(ladynana): propagate the actual error message
"Send frame to outgoing_frames failed."); // from EventEngine.
return absl::UnavailableError(
"Transport closed due to endpoint write/read "
"failed.");
} }
return absl::OkStatus(); return absl::OkStatus();
}); });
})); }),
// Continuously receive server frames from endpoints and save
// results to call_args.
Loop([server_initial_metadata = call_args.server_initial_metadata,
server_to_client_messages =
call_args.server_to_client_messages,
receiver = std::move(pipe_server_frames.receiver)]() mutable {
return TrySeq(
// Receive incoming server frame.
receiver.Next(),
// Save incomming frame results to call_args.
[server_initial_metadata, server_to_client_messages](
absl::optional<ServerFrame> server_frame) mutable {
bool transport_closed = false;
ServerFragmentFrame frame;
if (!server_frame.has_value()) {
// Incoming server frame pipe is closed, which only
// happens when transport is aborted.
transport_closed = true;
} else {
frame = std::move(
absl::get<ServerFragmentFrame>(*server_frame));
};
bool has_headers = (frame.headers != nullptr);
bool has_message = (frame.message != nullptr);
bool has_trailers = (frame.trailers != nullptr);
return TrySeq(
If((!transport_closed) && has_headers,
[server_initial_metadata,
headers = std::move(frame.headers)]() mutable {
return server_initial_metadata->Push(
std::move(headers));
},
[] { return false; }),
If((!transport_closed) && has_message,
[server_to_client_messages,
message = std::move(frame.message)]() mutable {
return server_to_client_messages->Push(
std::move(message));
},
[] { return false; }),
If((!transport_closed) && has_trailers,
[trailers = std::move(frame.trailers)]() mutable
-> LoopCtl<ServerMetadataHandle> {
return std::move(trailers);
},
[transport_closed]()
-> LoopCtl<ServerMetadataHandle> {
if (transport_closed) {
// TODO(ladynana): propagate the actual error
// message from EventEngine.
return ServerMetadataFromStatus(
absl::UnavailableError(
"Transport closed due to endpoint "
"write/read failed."));
}
return Continue();
}));
});
})),
[](std::tuple<Empty, ServerMetadataHandle> ret) {
return std::move(std::get<1>(ret));
});
} }
private: private:
// Max buffer is set to 4, so that for stream writes each time it will queue // Max buffer is set to 4, so that for stream writes each time it will queue
// at most 2 frames. // at most 2 frames.
MpscReceiver<ClientFrame> outgoing_frames_; MpscReceiver<ClientFrame> outgoing_frames_;
Mutex mu_; // Queue size of each stream pipe is set to 2, so that for each stream read it
uint32_t next_stream_id_ ABSL_GUARDED_BY(mu_) = 1; // will queue at most 2 frames.
static const size_t server_frame_queue_size_ = 2;
// Assigned aligned bytes from setting frame. // Assigned aligned bytes from setting frame.
size_t aligned_bytes = 64; size_t aligned_bytes = 64;
Mutex mu_;
uint32_t next_stream_id_ ABSL_GUARDED_BY(mu_) = 1;
// Map of stream incoming server frames, key is stream_id.
std::map<uint32_t, std::shared_ptr<InterActivityPipe<
ServerFrame, server_frame_queue_size_>::Sender>>
stream_map_ ABSL_GUARDED_BY(mu_);
ActivityPtr writer_; ActivityPtr writer_;
ActivityPtr reader_; ActivityPtr reader_;
std::unique_ptr<PromiseEndpoint> control_endpoint_; std::unique_ptr<PromiseEndpoint> control_endpoint_;
std::unique_ptr<PromiseEndpoint> data_endpoint_; std::unique_ptr<PromiseEndpoint> data_endpoint_;
SliceBuffer control_endpoint_write_buffer_; SliceBuffer control_endpoint_write_buffer_;
SliceBuffer data_endpoint_write_buffer_; SliceBuffer data_endpoint_write_buffer_;
SliceBuffer control_endpoint_read_buffer_;
SliceBuffer data_endpoint_read_buffer_;
std::unique_ptr<HPackCompressor> hpack_compressor_; std::unique_ptr<HPackCompressor> hpack_compressor_;
std::unique_ptr<HPackParser> hpack_parser_;
std::shared_ptr<FrameHeader> frame_header_;
MemoryAllocator memory_allocator_;
ScopedArenaPtr arena_;
promise_detail::Context<Arena> context_;
// Use to synchronize writer_ and reader_ activity with outside activities; // Use to synchronize writer_ and reader_ activity with outside activities;
std::shared_ptr<grpc_event_engine::experimental::EventEngine> event_engine_; std::shared_ptr<grpc_event_engine::experimental::EventEngine> event_engine_;
}; };

@ -32,6 +32,8 @@
#include "src/core/lib/gprpp/bitset.h" #include "src/core/lib/gprpp/bitset.h"
#include "src/core/lib/gprpp/no_destruct.h" #include "src/core/lib/gprpp/no_destruct.h"
#include "src/core/lib/gprpp/status_helper.h" #include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h" #include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h" #include "src/core/lib/slice/slice_buffer.h"
@ -134,7 +136,9 @@ absl::StatusOr<Arena::PoolPtr<Metadata>> ReadMetadata(
absl::BitGenRef bitsrc) { absl::BitGenRef bitsrc) {
if (!maybe_slices.ok()) return maybe_slices.status(); if (!maybe_slices.ok()) return maybe_slices.status();
auto& slices = *maybe_slices; auto& slices = *maybe_slices;
Arena::PoolPtr<Metadata> metadata; auto arena = GetContext<Arena>();
GPR_ASSERT(arena != nullptr);
Arena::PoolPtr<Metadata> metadata = arena->MakePooled<Metadata>(arena);
parser->BeginFrame( parser->BeginFrame(
metadata.get(), std::numeric_limits<uint32_t>::max(), metadata.get(), std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(),

@ -97,6 +97,7 @@ struct ServerFragmentFrame final : public FrameInterface {
FrameHeader frame_header; FrameHeader frame_header;
ServerMetadataHandle headers; ServerMetadataHandle headers;
MessageHandle message;
ServerMetadataHandle trailers; ServerMetadataHandle trailers;
bool operator==(const ServerFragmentFrame& other) const { bool operator==(const ServerFragmentFrame& other) const {

@ -229,30 +229,36 @@ static void send_goaway(grpc_chttp2_transport* t, grpc_error_handle error,
#define GRPC_ARG_SETTINGS_TIMEOUT "grpc.http2.settings_timeout" #define GRPC_ARG_SETTINGS_TIMEOUT "grpc.http2.settings_timeout"
namespace { namespace {
grpc_core::CallTracerInterface* CallTracerIfEnabled(grpc_chttp2_stream* s) {
using TaskHandle = ::grpc_event_engine::experimental::EventEngine::TaskHandle;
grpc_core::CallTracerInterface* CallTracerIfSampled(grpc_chttp2_stream* s) {
if (s->context == nullptr || !grpc_core::IsTraceRecordCallopsEnabled()) { if (s->context == nullptr || !grpc_core::IsTraceRecordCallopsEnabled()) {
return nullptr; return nullptr;
} }
return static_cast<grpc_core::CallTracerInterface*>( auto* call_tracer = static_cast<grpc_core::CallTracerInterface*>(
static_cast<grpc_call_context_element*>( static_cast<grpc_call_context_element*>(
s->context)[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE] s->context)[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE]
.value); .value);
if (call_tracer == nullptr || !call_tracer->IsSampled()) {
return nullptr;
}
return call_tracer;
} }
std::shared_ptr<grpc_core::TcpTracerInterface> TcpTracerIfEnabled( std::shared_ptr<grpc_core::TcpTracerInterface> TcpTracerIfSampled(
grpc_chttp2_stream* s) { grpc_chttp2_stream* s) {
if (s->context == nullptr || !s->traced || if (s->context == nullptr || !grpc_core::IsTraceRecordCallopsEnabled()) {
!grpc_core::IsTraceRecordCallopsEnabled()) {
return nullptr; return nullptr;
} }
auto* call_tracer = static_cast<grpc_core::CallTracerInterface*>( auto* call_attempt_tracer = static_cast<grpc_core::CallTracerInterface*>(
static_cast<grpc_call_context_element*>( static_cast<grpc_call_context_element*>(
s->context)[GRPC_CONTEXT_CALL_TRACER] s->context)[GRPC_CONTEXT_CALL_TRACER]
.value); .value);
if (!call_tracer) { if (call_attempt_tracer == nullptr || !call_attempt_tracer->IsSampled()) {
return nullptr; return nullptr;
} }
return call_tracer->StartNewTcpTrace(); return call_attempt_tracer->StartNewTcpTrace();
} }
grpc_core::WriteTimestampsCallback g_write_timestamps_callback = nullptr; grpc_core::WriteTimestampsCallback g_write_timestamps_callback = nullptr;
@ -497,10 +503,8 @@ static void read_channel_args(grpc_chttp2_transport* t,
if (max_requests_per_read.has_value()) { if (max_requests_per_read.has_value()) {
t->max_requests_per_read = t->max_requests_per_read =
grpc_core::Clamp(*max_requests_per_read, 1, 10000); grpc_core::Clamp(*max_requests_per_read, 1, 10000);
} else if (grpc_core::IsChttp2BatchRequestsEnabled()) {
t->max_requests_per_read = 32;
} else { } else {
t->max_requests_per_read = std::numeric_limits<size_t>::max(); t->max_requests_per_read = 32;
} }
if (channel_args.GetBool(GRPC_ARG_ENABLE_CHANNELZ) if (channel_args.GetBool(GRPC_ARG_ENABLE_CHANNELZ)
@ -517,8 +521,8 @@ static void read_channel_args(grpc_chttp2_transport* t,
t->ack_pings = channel_args.GetBool("grpc.http2.ack_pings").value_or(true); t->ack_pings = channel_args.GetBool("grpc.http2.ack_pings").value_or(true);
t->allow_tarpit = channel_args.GetBool(GRPC_ARG_HTTP_ALLOW_TARPIT) t->allow_tarpit =
.value_or(grpc_core::IsTarpitEnabled()); channel_args.GetBool(GRPC_ARG_HTTP_ALLOW_TARPIT).value_or(true);
t->min_tarpit_duration_ms = t->min_tarpit_duration_ms =
channel_args channel_args
.GetDurationFromIntMillis(GRPC_ARG_HTTP_TARPIT_MIN_DURATION_MS) .GetDurationFromIntMillis(GRPC_ARG_HTTP_TARPIT_MIN_DURATION_MS)
@ -800,41 +804,33 @@ static void close_transport_locked(grpc_chttp2_transport* t,
t->closed_with_error = error; t->closed_with_error = error;
connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, absl::Status(), connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, absl::Status(),
"close_transport"); "close_transport");
if (t->keepalive_ping_timeout_handle != if (t->keepalive_ping_timeout_handle != TaskHandle::kInvalid) {
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid) { t->event_engine->Cancel(std::exchange(t->keepalive_ping_timeout_handle,
t->event_engine->Cancel(std::exchange( TaskHandle::kInvalid));
t->keepalive_ping_timeout_handle,
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid));
}
if (t->settings_ack_watchdog !=
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid) {
t->event_engine->Cancel(std::exchange(
t->settings_ack_watchdog,
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid));
}
if (t->delayed_ping_timer_handle.has_value()) {
if (t->event_engine->Cancel(*t->delayed_ping_timer_handle)) {
t->delayed_ping_timer_handle.reset();
}
} }
if (t->next_bdp_ping_timer_handle.has_value()) { if (t->settings_ack_watchdog != TaskHandle::kInvalid) {
if (t->event_engine->Cancel(*t->next_bdp_ping_timer_handle)) { t->event_engine->Cancel(
t->next_bdp_ping_timer_handle.reset(); std::exchange(t->settings_ack_watchdog, TaskHandle::kInvalid));
} }
if (t->delayed_ping_timer_handle != TaskHandle::kInvalid &&
t->event_engine->Cancel(t->delayed_ping_timer_handle)) {
t->delayed_ping_timer_handle = TaskHandle::kInvalid;
}
if (t->next_bdp_ping_timer_handle != TaskHandle::kInvalid &&
t->event_engine->Cancel(t->next_bdp_ping_timer_handle)) {
t->next_bdp_ping_timer_handle = TaskHandle::kInvalid;
} }
switch (t->keepalive_state) { switch (t->keepalive_state) {
case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING: case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING:
if (t->keepalive_ping_timer_handle.has_value()) { if (t->keepalive_ping_timer_handle != TaskHandle::kInvalid &&
if (t->event_engine->Cancel(*t->keepalive_ping_timer_handle)) { t->event_engine->Cancel(t->keepalive_ping_timer_handle)) {
t->keepalive_ping_timer_handle.reset(); t->keepalive_ping_timer_handle = TaskHandle::kInvalid;
}
} }
break; break;
case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING: case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING:
if (t->keepalive_ping_timer_handle.has_value()) { if (t->keepalive_ping_timer_handle != TaskHandle::kInvalid &&
if (t->event_engine->Cancel(*t->keepalive_ping_timer_handle)) { t->event_engine->Cancel(t->keepalive_ping_timer_handle)) {
t->keepalive_ping_timer_handle.reset(); t->keepalive_ping_timer_handle = TaskHandle::kInvalid;
}
} }
break; break;
case GRPC_CHTTP2_KEEPALIVE_STATE_DYING: case GRPC_CHTTP2_KEEPALIVE_STATE_DYING:
@ -1471,8 +1467,8 @@ static void perform_stream_op_locked(void* stream_op,
s->context = op->payload->context; s->context = op->payload->context;
s->traced = op->is_traced; s->traced = op->is_traced;
s->call_tracer = CallTracerIfEnabled(s); s->call_tracer = CallTracerIfSampled(s);
s->tcp_tracer = TcpTracerIfEnabled(s); s->tcp_tracer = TcpTracerIfSampled(s);
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"perform_stream_op_locked[s=%p; op=%p]: %s; on_complete = %p", s, "perform_stream_op_locked[s=%p; op=%p]: %s; on_complete = %p", s,
@ -1834,8 +1830,8 @@ static void retry_initiate_ping_locked(
grpc_core::RefCountedPtr<grpc_chttp2_transport> t, grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
GRPC_UNUSED grpc_error_handle error) { GRPC_UNUSED grpc_error_handle error) {
GPR_DEBUG_ASSERT(error.ok()); GPR_DEBUG_ASSERT(error.ok());
GPR_ASSERT(t->delayed_ping_timer_handle.has_value()); GPR_ASSERT(t->delayed_ping_timer_handle != TaskHandle::kInvalid);
t->delayed_ping_timer_handle.reset(); t->delayed_ping_timer_handle = TaskHandle::kInvalid;
grpc_chttp2_initiate_write(t.get(), grpc_chttp2_initiate_write(t.get(),
GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING); GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING);
} }
@ -2828,7 +2824,6 @@ static void read_action_parse_loop_locked(
} }
close_transport_locked(t.get(), error); close_transport_locked(t.get(), error);
t->endpoint_reading = 0;
} else if (t->closed_with_error.ok()) { } else if (t->closed_with_error.ok()) {
keep_reading = true; keep_reading = true;
// Since we have read a byte, reset the keepalive timer // Since we have read a byte, reset the keepalive timer
@ -2857,17 +2852,15 @@ static void read_action_locked(
grpc_error_handle error) { grpc_error_handle error) {
// got an incoming read, cancel any pending keepalive timers // got an incoming read, cancel any pending keepalive timers
t->keepalive_incoming_data_wanted = false; t->keepalive_incoming_data_wanted = false;
if (t->keepalive_ping_timeout_handle != if (t->keepalive_ping_timeout_handle != TaskHandle::kInvalid) {
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_ping_trace) || if (GRPC_TRACE_FLAG_ENABLED(grpc_ping_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) { GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"%s[%p]: Clear keepalive timer because data was received", "%s[%p]: Clear keepalive timer because data was received",
t->is_client ? "CLIENT" : "SERVER", t.get()); t->is_client ? "CLIENT" : "SERVER", t.get());
} }
t->event_engine->Cancel(std::exchange( t->event_engine->Cancel(
t->keepalive_ping_timeout_handle, std::exchange(t->keepalive_ping_timeout_handle, TaskHandle::kInvalid));
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid));
} }
grpc_error_handle err = error; grpc_error_handle err = error;
if (!err.ok()) { if (!err.ok()) {
@ -2960,7 +2953,7 @@ static void finish_bdp_ping_locked(
t->flow_control.bdp_estimator()->CompletePing(); t->flow_control.bdp_estimator()->CompletePing();
grpc_chttp2_act_on_flowctl_action(t->flow_control.PeriodicUpdate(), t.get(), grpc_chttp2_act_on_flowctl_action(t->flow_control.PeriodicUpdate(), t.get(),
nullptr); nullptr);
GPR_ASSERT(!t->next_bdp_ping_timer_handle.has_value()); GPR_ASSERT(t->next_bdp_ping_timer_handle == TaskHandle::kInvalid);
t->next_bdp_ping_timer_handle = t->next_bdp_ping_timer_handle =
t->event_engine->RunAfter(next_ping - grpc_core::Timestamp::Now(), [t] { t->event_engine->RunAfter(next_ping - grpc_core::Timestamp::Now(), [t] {
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
@ -2980,8 +2973,8 @@ static void next_bdp_ping_timer_expired_locked(
grpc_core::RefCountedPtr<grpc_chttp2_transport> t, grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
GRPC_UNUSED grpc_error_handle error) { GRPC_UNUSED grpc_error_handle error) {
GPR_DEBUG_ASSERT(error.ok()); GPR_DEBUG_ASSERT(error.ok());
GPR_ASSERT(t->next_bdp_ping_timer_handle.has_value()); GPR_ASSERT(t->next_bdp_ping_timer_handle != TaskHandle::kInvalid);
t->next_bdp_ping_timer_handle.reset(); t->next_bdp_ping_timer_handle = TaskHandle::kInvalid;
if (t->flow_control.bdp_estimator()->accumulator() == 0) { if (t->flow_control.bdp_estimator()->accumulator() == 0) {
// Block the bdp ping till we receive more data. // Block the bdp ping till we receive more data.
t->bdp_ping_blocked = true; t->bdp_ping_blocked = true;
@ -3050,8 +3043,8 @@ static void init_keepalive_ping_locked(
GRPC_UNUSED grpc_error_handle error) { GRPC_UNUSED grpc_error_handle error) {
GPR_DEBUG_ASSERT(error.ok()); GPR_DEBUG_ASSERT(error.ok());
GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING); GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING);
GPR_ASSERT(t->keepalive_ping_timer_handle.has_value()); GPR_ASSERT(t->keepalive_ping_timer_handle != TaskHandle::kInvalid);
t->keepalive_ping_timer_handle.reset(); t->keepalive_ping_timer_handle = TaskHandle::kInvalid;
if (t->destroying || !t->closed_with_error.ok()) { if (t->destroying || !t->closed_with_error.ok()) {
t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING; t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
} else { } else {
@ -3092,7 +3085,7 @@ static void finish_keepalive_ping_locked(
std::string(t->peer_string.as_string_view()).c_str()); std::string(t->peer_string.as_string_view()).c_str());
} }
t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
GPR_ASSERT(!t->keepalive_ping_timer_handle.has_value()); GPR_ASSERT(t->keepalive_ping_timer_handle == TaskHandle::kInvalid);
t->keepalive_ping_timer_handle = t->keepalive_ping_timer_handle =
t->event_engine->RunAfter(t->keepalive_time, [t] { t->event_engine->RunAfter(t->keepalive_time, [t] {
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
@ -3104,22 +3097,21 @@ static void finish_keepalive_ping_locked(
} }
static void maybe_reset_keepalive_ping_timer_locked(grpc_chttp2_transport* t) { static void maybe_reset_keepalive_ping_timer_locked(grpc_chttp2_transport* t) {
if (t->keepalive_ping_timer_handle.has_value()) { if (t->keepalive_ping_timer_handle != TaskHandle::kInvalid &&
if (t->event_engine->Cancel(*t->keepalive_ping_timer_handle)) { t->event_engine->Cancel(t->keepalive_ping_timer_handle)) {
// Cancel succeeds, resets the keepalive ping timer. Note that we don't // Cancel succeeds, resets the keepalive ping timer. Note that we don't
// need to Ref or Unref here since we still hold the Ref. // need to Ref or Unref here since we still hold the Ref.
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) || if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) { GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
gpr_log(GPR_INFO, "%s: Keepalive ping cancelled. Resetting timer.", gpr_log(GPR_INFO, "%s: Keepalive ping cancelled. Resetting timer.",
std::string(t->peer_string.as_string_view()).c_str()); std::string(t->peer_string.as_string_view()).c_str());
}
t->keepalive_ping_timer_handle = t->event_engine->RunAfter(
t->keepalive_time, [t = t->Ref()]() mutable {
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
grpc_core::ExecCtx exec_ctx;
init_keepalive_ping(std::move(t));
});
} }
t->keepalive_ping_timer_handle =
t->event_engine->RunAfter(t->keepalive_time, [t = t->Ref()]() mutable {
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
grpc_core::ExecCtx exec_ctx;
init_keepalive_ping(std::move(t));
});
} }
} }

@ -119,6 +119,15 @@ class HttpAnnotation : public CallTracerAnnotationInterface::Annotation {
std::string ToString() const override; std::string ToString() const override;
Type http_type() const { return type_; }
Timestamp time() const { return time_; }
absl::optional<chttp2::TransportFlowControl::Stats> transport_stats() const {
return transport_stats_;
}
absl::optional<chttp2::StreamFlowControl::Stats> stream_stats() const {
return stream_stats_;
}
private: private:
const Type type_; const Type type_;
const Timestamp time_; const Timestamp time_;

@ -422,23 +422,9 @@ FlowControlAction StreamFlowControl::UpdateAction(FlowControlAction action) {
} }
// min_progress_size_ > 0 means we have a reader ready to read. // min_progress_size_ > 0 means we have a reader ready to read.
if (min_progress_size_ > 0) { if (min_progress_size_ > 0) {
if (IsLazierStreamUpdatesEnabled()) { if (announced_window_delta_ <=
if (announced_window_delta_ <= -static_cast<int64_t>(tfc_->sent_init_window()) / 2) {
-static_cast<int64_t>(tfc_->sent_init_window()) / 2) { urgency = FlowControlAction::Urgency::UPDATE_IMMEDIATELY;
urgency = FlowControlAction::Urgency::UPDATE_IMMEDIATELY;
}
} else {
// If we're into initial window to receive that data we should wake up
// and send an update.
if (announced_window_delta_ < 0) {
urgency = FlowControlAction::Urgency::UPDATE_IMMEDIATELY;
} else if (announced_window_delta_ == 0 &&
tfc_->queued_init_window() == 0) {
// Special case when initial window size is zero, meaning that
// announced_window_delta cannot become negative (it may already be so
// however).
urgency = FlowControlAction::Urgency::UPDATE_IMMEDIATELY;
}
} }
} }
action.set_send_stream_update(urgency); action.set_send_stream_update(urgency);

@ -126,7 +126,7 @@ grpc_error_handle grpc_chttp2_rst_stream_parser_parse(void* parser,
grpc_core::StatusIntProperty::kHttp2Error, grpc_core::StatusIntProperty::kHttp2Error,
static_cast<intptr_t>(reason)); static_cast<intptr_t>(reason));
} }
if (grpc_core::IsPingOnRstStreamEnabled() && !t->is_client && if (!t->is_client &&
absl::Bernoulli(t->bitgen, t->ping_on_rst_stream_percent / 100.0)) { absl::Bernoulli(t->bitgen, t->ping_on_rst_stream_percent / 100.0)) {
++t->num_pending_induced_frames; ++t->num_pending_induced_frames;
t->ping_callbacks.RequestPing(); t->ping_callbacks.RequestPing();

@ -475,31 +475,25 @@ void Encoder::EncodeRepeatingSliceValue(const absl::string_view& key,
void TimeoutCompressorImpl::EncodeWith(absl::string_view key, void TimeoutCompressorImpl::EncodeWith(absl::string_view key,
Timestamp deadline, Encoder* encoder) { Timestamp deadline, Encoder* encoder) {
Timeout timeout = Timeout::FromDuration(deadline - Timestamp::Now()); const Timeout timeout = Timeout::FromDuration(deadline - Timestamp::Now());
auto& table = encoder->hpack_table(); auto& table = encoder->hpack_table();
for (auto it = previous_timeouts_.begin(); it != previous_timeouts_.end(); for (size_t i = 0; i < kNumPreviousValues; i++) {
++it) { const auto& previous = previous_timeouts_[i];
double ratio = timeout.RatioVersus(it->timeout); if (!table.ConvertableToDynamicIndex(previous.index)) continue;
const double ratio = timeout.RatioVersus(previous.timeout);
// If the timeout we're sending is shorter than a previous timeout, but // If the timeout we're sending is shorter than a previous timeout, but
// within 3% of it, we'll consider sending it. // within 3% of it, we'll consider sending it.
if (ratio > -3 && ratio <= 0 && if (ratio > -3 && ratio <= 0) {
table.ConvertableToDynamicIndex(it->index)) { encoder->EmitIndexed(table.DynamicIndex(previous.index));
encoder->EmitIndexed(table.DynamicIndex(it->index));
// Put this timeout to the front of the queue - forces common timeouts to
// be considered earlier.
std::swap(*it, *previous_timeouts_.begin());
return; return;
} }
} }
// Clean out some expired timeouts.
while (!previous_timeouts_.empty() &&
!table.ConvertableToDynamicIndex(previous_timeouts_.back().index)) {
previous_timeouts_.pop_back();
}
Slice encoded = timeout.Encode(); Slice encoded = timeout.Encode();
uint32_t index = encoder->EmitLitHdrWithNonBinaryStringKeyIncIdx( uint32_t index = encoder->EmitLitHdrWithNonBinaryStringKeyIncIdx(
Slice::FromStaticString(key), std::move(encoded)); Slice::FromStaticString(key), std::move(encoded));
previous_timeouts_.push_back(PreviousTimeout{timeout, index}); uint32_t i = next_previous_value_;
++next_previous_value_;
previous_timeouts_[i % kNumPreviousValues] = PreviousTimeout{timeout, index};
} }
Encoder::Encoder(HPackCompressor* compressor, bool use_true_binary_metadata, Encoder::Encoder(HPackCompressor* compressor, bool use_true_binary_metadata,

@ -276,8 +276,10 @@ class Compressor<MetadataTrait, SmallSetOfValuesCompressor> {
}; };
struct PreviousTimeout { struct PreviousTimeout {
Timeout timeout; Timeout timeout = Timeout::FromDuration(Duration::Zero());
uint32_t index; // Dynamic table index of a previously sent timeout
// 0 is guaranteed not in the dynamic table so is a safe initializer
uint32_t index = 0;
}; };
class TimeoutCompressorImpl { class TimeoutCompressorImpl {
@ -285,7 +287,9 @@ class TimeoutCompressorImpl {
void EncodeWith(absl::string_view key, Timestamp deadline, Encoder* encoder); void EncodeWith(absl::string_view key, Timestamp deadline, Encoder* encoder);
private: private:
std::vector<PreviousTimeout> previous_timeouts_; static constexpr const size_t kNumPreviousValues = 5;
PreviousTimeout previous_timeouts_[kNumPreviousValues];
uint32_t next_previous_value_ = 0;
}; };
template <typename MetadataTrait> template <typename MetadataTrait>

@ -21,8 +21,7 @@
#include <stdint.h> #include <stdint.h>
#include <limits> #include <limits>
#include <vector>
#include "absl/container/inlined_vector.h"
#include "src/core/ext/transport/chttp2/transport/hpack_constants.h" #include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
@ -59,6 +58,7 @@ class HPackEncoderTable {
table_elems_ - index; table_elems_ - index;
} }
// Check if an element index is convertable to a dynamic index // Check if an element index is convertable to a dynamic index
// Note that 0 is always not convertable
bool ConvertableToDynamicIndex(uint32_t index) const { bool ConvertableToDynamicIndex(uint32_t index) const {
return index > tail_remote_index_; return index > tail_remote_index_;
} }
@ -73,8 +73,7 @@ class HPackEncoderTable {
uint32_t table_elems_ = 0; uint32_t table_elems_ = 0;
uint32_t table_size_ = 0; uint32_t table_size_ = 0;
// The size of each element in the HPACK table. // The size of each element in the HPACK table.
absl::InlinedVector<EntrySize, hpack_constants::kInitialTableEntries> std::vector<EntrySize> elem_size_;
elem_size_;
}; };
} // namespace grpc_core } // namespace grpc_core

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save