grpc 1.83.1 → 1.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +21 -17
  3. data/include/grpc/credentials.h +10 -0
  4. data/include/grpc/grpc_security_constants.h +2 -0
  5. data/include/grpc/impl/channel_arg_names.h +9 -0
  6. data/src/core/call/call_filters.h +4 -2
  7. data/src/core/call/client_call.cc +20 -8
  8. data/src/core/call/client_call.h +4 -0
  9. data/src/core/call/interception_chain.cc +2 -0
  10. data/src/core/call/interception_chain.h +14 -1
  11. data/src/core/call/metadata.cc +1 -3
  12. data/src/core/call/metadata_batch.h +13 -5
  13. data/src/core/call/server_call.cc +31 -14
  14. data/src/core/call/server_call.h +4 -0
  15. data/src/core/channelz/text_encode.cc +9 -4
  16. data/src/core/channelz/v2tov1/convert.cc +2 -2
  17. data/src/core/client_channel/backup_poller.cc +1 -2
  18. data/src/core/client_channel/client_channel.cc +6 -33
  19. data/src/core/client_channel/client_channel_filter.cc +22 -55
  20. data/src/core/client_channel/client_channel_filter.h +2 -2
  21. data/src/core/client_channel/client_channel_service_config.cc +3 -19
  22. data/src/core/client_channel/direct_channel.cc +7 -1
  23. data/src/core/client_channel/direct_channel.h +2 -2
  24. data/src/core/client_channel/load_balanced_call_destination.cc +5 -3
  25. data/src/core/client_channel/retry_filter_legacy_call_data.cc +5 -12
  26. data/src/core/client_channel/subchannel.cc +310 -1058
  27. data/src/core/client_channel/subchannel.h +44 -329
  28. data/src/core/client_channel/subchannel_metrics.cc +48 -0
  29. data/src/core/client_channel/subchannel_metrics.h +60 -0
  30. data/src/core/credentials/call/external/file_external_account_credentials.cc +1 -1
  31. data/src/core/credentials/call/external/url_external_account_credentials.cc +2 -3
  32. data/src/core/credentials/call/gcp_service_account_identity/gcp_service_account_identity_credentials.cc +8 -24
  33. data/src/core/credentials/call/gcp_service_account_identity/gcp_service_account_identity_credentials.h +3 -6
  34. data/src/core/credentials/call/gdch_service_account/gdch_service_account_credentials.cc +525 -0
  35. data/src/core/credentials/call/gdch_service_account/gdch_service_account_credentials.h +138 -0
  36. data/src/core/credentials/call/json_util.h +1 -0
  37. data/src/core/credentials/call/jwt/json_token.cc +10 -2
  38. data/src/core/credentials/call/jwt/jwt_verifier.cc +15 -1
  39. data/src/core/credentials/call/jwt_token_file/jwt_token_file_call_credentials.cc +1 -1
  40. data/src/core/credentials/call/oauth2/oauth2_credentials.cc +42 -79
  41. data/src/core/credentials/call/oauth2/oauth2_credentials.h +2 -5
  42. data/src/core/credentials/call/token_fetcher/token_fetcher_credentials.cc +52 -31
  43. data/src/core/credentials/call/token_fetcher/token_fetcher_credentials.h +21 -8
  44. data/src/core/credentials/transport/google_default/google_default_credentials.cc +3 -4
  45. data/src/core/credentials/transport/ssl/ssl_credentials.cc +59 -72
  46. data/src/core/credentials/transport/ssl/ssl_credentials.h +9 -8
  47. data/src/core/credentials/transport/ssl/ssl_security_connector.cc +12 -6
  48. data/src/core/credentials/transport/ssl/ssl_security_connector.h +4 -4
  49. data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.cc +29 -18
  50. data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.h +9 -6
  51. data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.cc +45 -56
  52. data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.h +5 -4
  53. data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.h +26 -0
  54. data/src/core/credentials/transport/tls/grpc_tls_crl_provider.cc +1 -1
  55. data/src/core/credentials/transport/tls/load_system_roots.h +2 -6
  56. data/src/core/credentials/transport/tls/load_system_roots_fallback.cc +2 -4
  57. data/src/core/credentials/transport/tls/load_system_roots_supported.cc +13 -15
  58. data/src/core/credentials/transport/tls/load_system_roots_supported.h +3 -2
  59. data/src/core/credentials/transport/tls/load_system_roots_windows.cc +5 -8
  60. data/src/core/credentials/transport/tls/spiffe_utils.cc +1 -1
  61. data/src/core/credentials/transport/tls/ssl_utils.cc +39 -28
  62. data/src/core/credentials/transport/tls/ssl_utils.h +12 -49
  63. data/src/core/credentials/transport/tls/tls_security_connector.cc +48 -33
  64. data/src/core/credentials/transport/tls/tls_security_connector.h +31 -10
  65. data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc +15 -11
  66. data/src/core/ext/filters/http/http_filters_plugin.cc +20 -9
  67. data/src/core/ext/filters/rbac/rbac_filter.cc +43 -21
  68. data/src/core/ext/filters/rbac/rbac_filter.h +21 -3
  69. data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +2 -2
  70. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +1 -1
  71. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +6 -20
  72. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +32 -67
  73. data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -0
  74. data/src/core/ext/transport/chttp2/transport/flow_control.h +78 -4
  75. data/src/core/ext/transport/chttp2/transport/frame.h +2 -0
  76. data/src/core/ext/transport/chttp2/transport/frame_data.cc +3 -4
  77. data/src/core/ext/transport/chttp2/transport/goaway.h +7 -0
  78. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +5 -3
  79. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +3 -1
  80. data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +141 -130
  81. data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +22 -22
  82. data/src/core/ext/transport/chttp2/transport/http2_server_transport.cc +402 -269
  83. data/src/core/ext/transport/chttp2/transport/http2_server_transport.h +80 -49
  84. data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +1 -2
  85. data/src/core/ext/transport/chttp2/transport/http2_status.h +38 -37
  86. data/src/core/ext/transport/chttp2/transport/http2_transport.cc +178 -5
  87. data/src/core/ext/transport/chttp2/transport/http2_transport.h +345 -5
  88. data/src/core/ext/transport/chttp2/transport/parsing.cc +5 -5
  89. data/src/core/ext/transport/chttp2/transport/ping_promise.cc +3 -2
  90. data/src/core/ext/transport/chttp2/transport/ping_promise.h +25 -5
  91. data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +3 -4
  92. data/src/core/ext/transport/chttp2/transport/read_context.h +30 -3
  93. data/src/core/ext/transport/chttp2/transport/stream.h +65 -23
  94. data/src/core/ext/transport/chttp2/transport/writing.cc +0 -3
  95. data/src/core/ext/transport/inproc/inproc_transport.cc +1 -5
  96. data/src/core/ext/transport/inproc/legacy_inproc_transport.cc +4 -17
  97. data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upb.h +1912 -0
  98. data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upb_minitable.c +300 -0
  99. data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upb_minitable.h +37 -0
  100. data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upb.h +187 -0
  101. data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upb_minitable.c +64 -0
  102. data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upb_minitable.h +31 -0
  103. data/src/core/ext/upb-gen/envoy/service/ext_proc/v3/external_processor.upb.h +2362 -0
  104. data/src/core/ext/upb-gen/envoy/service/ext_proc/v3/external_processor.upb_minitable.c +556 -0
  105. data/src/core/ext/upb-gen/envoy/service/ext_proc/v3/external_processor.upb_minitable.h +47 -0
  106. data/src/core/ext/upb-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upb.h +5 -5
  107. data/src/core/ext/upb-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upb_minitable.c +3 -3
  108. data/src/core/ext/upb-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upb_minitable.h +5 -5
  109. data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upbdefs.c +453 -0
  110. data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upbdefs.h +67 -0
  111. data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upbdefs.c +142 -0
  112. data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upbdefs.h +37 -0
  113. data/src/core/ext/upbdefs-gen/grpc/channelz/v1/channelz.upbdefs.c +715 -0
  114. data/src/core/ext/upbdefs-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upbdefs.h +44 -44
  115. data/src/core/filter/auth/server_auth_filter.cc +2 -3
  116. data/src/core/filter/composite/composite_filter.cc +45 -33
  117. data/src/core/filter/composite/composite_filter.h +5 -4
  118. data/src/core/filter/ext_proc/ext_proc_filter.cc +224 -0
  119. data/src/core/filter/ext_proc/ext_proc_filter.h +155 -0
  120. data/src/core/filter/ext_proc/ext_proc_messages.cc +701 -0
  121. data/src/core/filter/ext_proc/ext_proc_messages.h +297 -0
  122. data/src/core/filter/filter_args.h +13 -2
  123. data/src/core/handshaker/http_connect/http_proxy_mapper.cc +30 -3
  124. data/src/core/handshaker/security/security_handshaker.cc +9 -6
  125. data/src/core/lib/channel/channel_stack.cc +3 -0
  126. data/src/core/lib/channel/channel_stack.h +2 -0
  127. data/src/core/lib/channel/channel_stack_builder_impl.cc +1 -2
  128. data/src/core/lib/channel/promise_based_filter.cc +132 -20
  129. data/src/core/lib/channel/promise_based_filter.h +42 -12
  130. data/src/core/lib/compression/compression_internal.cc +4 -5
  131. data/src/core/lib/debug/trace_flags.cc +8 -0
  132. data/src/core/lib/debug/trace_flags.h +3 -0
  133. data/src/core/lib/event_engine/ares_resolver.cc +54 -50
  134. data/src/core/lib/event_engine/ares_resolver.h +3 -2
  135. data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc +3 -3
  136. data/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc +4 -10
  137. data/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +74 -33
  138. data/src/core/lib/event_engine/posix_engine/posix_endpoint.h +4 -4
  139. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +6 -2
  140. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc +3 -0
  141. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h +3 -0
  142. data/src/core/lib/event_engine/windows/windows_endpoint.cc +1 -3
  143. data/src/core/lib/experiments/experiments.cc +60 -96
  144. data/src/core/lib/experiments/experiments.h +34 -50
  145. data/src/core/lib/iomgr/cfstream_handle.cc +2 -6
  146. data/src/core/lib/iomgr/endpoint_cfstream.cc +3 -10
  147. data/src/core/lib/iomgr/error.cc +2 -6
  148. data/src/core/lib/iomgr/error_cfstream.cc +1 -1
  149. data/src/core/lib/iomgr/ev_poll_posix.cc +5 -9
  150. data/src/core/lib/iomgr/event_engine_shims/closure.cc +1 -1
  151. data/src/core/lib/iomgr/event_engine_shims/endpoint.cc +1 -2
  152. data/src/core/lib/iomgr/event_engine_shims/tcp_client.cc +1 -2
  153. data/src/core/lib/iomgr/iomgr_posix.cc +0 -4
  154. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +0 -4
  155. data/src/core/lib/iomgr/iomgr_windows.cc +0 -4
  156. data/src/core/lib/iomgr/socket_factory_posix.h +1 -1
  157. data/src/core/lib/iomgr/socket_utils_posix.cc +3 -0
  158. data/src/core/lib/iomgr/socket_utils_posix.h +3 -0
  159. data/src/core/lib/iomgr/systemd_utils.cc +0 -1
  160. data/src/core/lib/iomgr/tcp_client.h +1 -1
  161. data/src/core/lib/iomgr/tcp_posix.cc +23 -15
  162. data/src/core/lib/iomgr/tcp_server.h +1 -1
  163. data/src/core/lib/iomgr/tcp_server_posix.cc +2 -3
  164. data/src/core/lib/iomgr/tcp_server_utils_posix.h +0 -1
  165. data/src/core/lib/iomgr/tcp_server_windows.cc +0 -1
  166. data/src/core/lib/iomgr/tcp_windows.cc +5 -10
  167. data/src/core/lib/iomgr/unix_sockets_posix.cc +2 -4
  168. data/src/core/lib/iomgr/unix_sockets_posix.h +3 -1
  169. data/src/core/lib/iomgr/vsock.h +3 -1
  170. data/src/core/lib/resource_quota/memory_quota.cc +1 -1
  171. data/src/core/lib/security/authorization/rbac_policy.cc +139 -56
  172. data/src/core/lib/security/authorization/rbac_policy.h +21 -3
  173. data/src/core/lib/surface/call.cc +3 -9
  174. data/src/core/lib/surface/call_utils.h +113 -0
  175. data/src/core/lib/surface/channel_create.cc +1 -1
  176. data/src/core/lib/surface/channel_create.h +0 -2
  177. data/src/core/lib/surface/channel_init.cc +77 -38
  178. data/src/core/lib/surface/channel_init.h +30 -16
  179. data/src/core/lib/surface/filter_stack_call.cc +5 -10
  180. data/src/core/lib/surface/init.cc +13 -27
  181. data/src/core/lib/surface/version.cc +1 -1
  182. data/src/core/lib/transport/error_utils.cc +0 -27
  183. data/src/core/lib/transport/error_utils.h +0 -16
  184. data/src/core/lib/transport/transport.h +7 -5
  185. data/src/core/load_balancing/pick_first/pick_first.cc +2 -0
  186. data/src/core/load_balancing/rls/rls.cc +28 -11
  187. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +33 -42
  188. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.h +0 -2
  189. data/src/core/load_balancing/xds/cds.cc +3 -1
  190. data/src/core/load_balancing/xds/xds_cluster_impl.cc +0 -1
  191. data/src/core/mitigation_engine/mitigation.h +14 -5
  192. data/src/core/mitigation_engine/mitigation_engine.h +7 -3
  193. data/src/core/mitigation_engine/mitigation_provider.h +2 -1
  194. data/src/core/plugin_registry/grpc_plugin_registry.cc +39 -8
  195. data/src/core/resolver/dns/{event_engine/event_engine_client_channel_resolver.cc → dns_resolver.cc} +42 -41
  196. data/src/core/resolver/dns/{event_engine/event_engine_client_channel_resolver.h → dns_resolver.h} +8 -5
  197. data/src/core/resolver/dns/{event_engine/service_config_helper.cc → service_config_helper.cc} +1 -1
  198. data/src/core/resolver/dns/{event_engine/service_config_helper.h → service_config_helper.h} +3 -3
  199. data/src/core/resolver/endpoint_addresses.h +3 -0
  200. data/src/core/resolver/google_c2p/google_c2p_resolver.cc +2 -1
  201. data/src/core/resolver/xds/xds_resolver.cc +35 -9
  202. data/src/core/server/server.cc +2 -6
  203. data/src/core/server/server_config_selector.h +18 -3
  204. data/src/core/server/server_config_selector_filter.cc +178 -91
  205. data/src/core/server/server_config_selector_filter.h +58 -3
  206. data/src/core/server/xds_server_config_fetcher.cc +196 -129
  207. data/src/core/server/xds_server_config_fetcher.h +49 -0
  208. data/src/core/server/xds_server_config_fetcher_legacy.cc +41 -37
  209. data/src/core/telemetry/histogram.h +94 -14
  210. data/src/core/telemetry/instrument.cc +179 -74
  211. data/src/core/telemetry/instrument.h +78 -30
  212. data/src/core/telemetry/metrics.h +5 -0
  213. data/src/core/{resolver/dns/dns_resolver_plugin.h → telemetry/telemetry_label.h} +12 -8
  214. data/src/core/tsi/alts/crypt/aes_gcm.cc +10 -13
  215. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +2 -2
  216. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +3 -1
  217. data/src/core/tsi/ssl_telemetry_utils.cc +216 -259
  218. data/src/core/tsi/ssl_telemetry_utils.h +12 -2
  219. data/src/core/tsi/ssl_transport_security.cc +238 -80
  220. data/src/core/tsi/ssl_transport_security.h +63 -33
  221. data/src/core/tsi/tls_telemetry.cc +31 -0
  222. data/src/core/tsi/tls_telemetry.h +47 -0
  223. data/src/core/tsi/transport_security.cc +2 -2
  224. data/src/core/tsi/transport_security.h +1 -1
  225. data/src/core/tsi/transport_security_interface.h +1 -1
  226. data/src/core/{resolver/dns/native/dns_resolver.h → util/address_sorting_init.cc} +21 -8
  227. data/src/core/{resolver/dns/c_ares/grpc_ares_wrapper_posix.cc → util/address_sorting_init.h} +7 -8
  228. data/src/core/util/http_client/httpcli.cc +16 -53
  229. data/src/core/util/http_client/httpcli.h +0 -7
  230. data/src/core/util/http_client/httpcli_security_connector.cc +13 -8
  231. data/src/core/util/linux/cpu.cc +1 -1
  232. data/src/core/util/load_file.cc +3 -9
  233. data/src/core/util/load_file.h +3 -4
  234. data/src/core/util/matchers.h +8 -0
  235. data/src/core/util/posix/cpu.cc +1 -1
  236. data/src/core/util/status_helper.cc +0 -20
  237. data/src/core/util/status_helper.h +3 -14
  238. data/src/core/xds/grpc/xds_audit_logger_registry.cc +51 -31
  239. data/src/core/xds/grpc/xds_audit_logger_registry.h +17 -3
  240. data/src/core/xds/grpc/xds_bootstrap_grpc.cc +2 -10
  241. data/src/core/xds/grpc/xds_bootstrap_grpc.h +8 -6
  242. data/src/core/xds/grpc/xds_bootstrap_grpc_builder.cc +488 -0
  243. data/src/core/xds/grpc/xds_bootstrap_grpc_builder.h +97 -0
  244. data/src/core/xds/grpc/xds_certificate_provider.cc +7 -7
  245. data/src/core/xds/grpc/xds_client_grpc.cc +4 -8
  246. data/src/core/xds/grpc/xds_client_grpc.h +0 -4
  247. data/src/core/xds/grpc/xds_cluster.h +1 -0
  248. data/src/core/xds/grpc/xds_cluster_parser.cc +1 -5
  249. data/src/core/xds/grpc/xds_cluster_parser.h +0 -2
  250. data/src/core/xds/grpc/xds_cluster_specifier_plugin.cc +0 -2
  251. data/src/core/xds/grpc/xds_cluster_specifier_plugin.h +0 -2
  252. data/src/core/xds/grpc/xds_common_types.cc +0 -91
  253. data/src/core/xds/grpc/xds_common_types.h +1 -47
  254. data/src/core/xds/grpc/xds_common_types_parser.cc +84 -378
  255. data/src/core/xds/grpc/xds_common_types_parser.h +9 -11
  256. data/src/core/xds/grpc/xds_endpoint_parser.cc +0 -2
  257. data/src/core/xds/grpc/xds_grpc_service_parser.cc +177 -0
  258. data/src/core/{resolver/dns/c_ares/dns_resolver_ares.h → xds/grpc/xds_grpc_service_parser.h} +14 -9
  259. data/src/core/xds/grpc/xds_http_composite_filter.cc +26 -21
  260. data/src/core/xds/grpc/xds_http_composite_filter.h +4 -3
  261. data/src/core/xds/grpc/xds_http_ext_proc_filter.cc +418 -0
  262. data/src/core/xds/grpc/xds_http_ext_proc_filter.h +89 -0
  263. data/src/core/xds/grpc/xds_http_fault_filter.cc +9 -12
  264. data/src/core/xds/grpc/xds_http_fault_filter.h +1 -4
  265. data/src/core/xds/grpc/xds_http_filter.cc +2 -1
  266. data/src/core/xds/grpc/xds_http_filter.h +6 -5
  267. data/src/core/xds/grpc/xds_http_filter_registry.cc +10 -127
  268. data/src/core/xds/grpc/xds_http_filter_registry.h +7 -59
  269. data/src/core/xds/grpc/xds_http_gcp_authn_filter.cc +13 -14
  270. data/src/core/xds/grpc/xds_http_gcp_authn_filter.h +3 -2
  271. data/src/core/xds/grpc/xds_http_rbac_filter.cc +403 -25
  272. data/src/core/xds/grpc/xds_http_rbac_filter.h +1 -3
  273. data/src/core/xds/grpc/xds_http_stateful_session_filter.cc +8 -13
  274. data/src/core/xds/grpc/xds_http_stateful_session_filter.h +1 -4
  275. data/src/core/xds/grpc/xds_lb_policy_registry.cc +0 -292
  276. data/src/core/xds/grpc/xds_lb_policy_registry.h +7 -3
  277. data/src/core/xds/grpc/xds_listener.cc +2 -0
  278. data/src/core/xds/grpc/xds_listener.h +5 -0
  279. data/src/core/xds/grpc/xds_listener_parser.cc +16 -11
  280. data/src/core/xds/grpc/xds_matcher_parse.h +3 -1
  281. data/src/core/xds/grpc/xds_metadata_parser.cc +6 -1
  282. data/src/core/xds/grpc/xds_metadata_parser.h +2 -0
  283. data/src/core/xds/grpc/xds_route_config.cc +2 -0
  284. data/src/core/xds/grpc/xds_route_config.h +3 -1
  285. data/src/core/xds/grpc/xds_route_config_parser.cc +13 -79
  286. data/src/core/xds/grpc/xds_route_config_parser.h +0 -3
  287. data/src/core/xds/grpc/xds_routing.cc +116 -69
  288. data/src/core/xds/grpc/xds_routing.h +19 -8
  289. data/src/core/xds/grpc/xds_tls_context.cc +117 -0
  290. data/src/core/xds/grpc/xds_tls_context.h +76 -0
  291. data/src/core/xds/grpc/xds_tls_context_parser.cc +275 -0
  292. data/src/core/xds/grpc/xds_tls_context_parser.h +35 -0
  293. data/src/core/xds/grpc/xds_transport_grpc.cc +41 -38
  294. data/src/core/xds/grpc/xds_transport_grpc.h +4 -2
  295. data/src/ruby/ext/grpc/rb_call.c +26 -15
  296. data/src/ruby/ext/grpc/rb_completion_queue.c +6 -5
  297. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  298. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
  299. data/src/ruby/lib/grpc/version.rb +1 -1
  300. data/src/ruby/pb/test/client.rb +5 -4
  301. data/src/ruby/spec/call_spec.rb +14 -0
  302. data/src/ruby/spec/generic/server_interceptors_spec.rb +3 -6
  303. metadata +50 -35
  304. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/channelz.upbdefs.c +0 -716
  305. data/src/core/lib/iomgr/resolve_address.cc +0 -59
  306. data/src/core/lib/iomgr/resolve_address.h +0 -125
  307. data/src/core/lib/iomgr/resolve_address_impl.h +0 -58
  308. data/src/core/lib/iomgr/resolve_address_posix.cc +0 -184
  309. data/src/core/lib/iomgr/resolve_address_posix.h +0 -78
  310. data/src/core/lib/iomgr/resolve_address_windows.cc +0 -169
  311. data/src/core/lib/iomgr/resolve_address_windows.h +0 -76
  312. data/src/core/resolver/dns/c_ares/dns_resolver_ares.cc +0 -781
  313. data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver.h +0 -93
  314. data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +0 -203
  315. data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +0 -838
  316. data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc +0 -1237
  317. data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.h +0 -130
  318. data/src/core/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +0 -35
  319. data/src/core/resolver/dns/dns_resolver_plugin.cc +0 -64
  320. data/src/core/resolver/dns/native/dns_resolver.cc +0 -173
  321. data/src/core/util/json/json_util.cc +0 -101
  322. data/src/core/util/json/json_util.h +0 -163
@@ -21,18 +21,15 @@
21
21
  #include <grpc/event_engine/event_engine.h>
22
22
  #include <grpc/grpc.h>
23
23
  #include <grpc/support/port_platform.h>
24
- #include <limits.h>
25
24
 
26
25
  #include <algorithm>
27
26
  #include <cstddef>
28
27
  #include <cstdint>
29
- #include <iterator>
30
28
  #include <memory>
31
29
  #include <optional>
32
30
  #include <string>
33
31
  #include <type_traits>
34
32
  #include <utility>
35
- #include <variant>
36
33
  #include <vector>
37
34
 
38
35
  #include "src/core/call/call_destination.h"
@@ -47,7 +44,6 @@
47
44
  #include "src/core/ext/transport/chttp2/transport/goaway.h"
48
45
  #include "src/core/ext/transport/chttp2/transport/header_assembler.h"
49
46
  #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
50
- #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
51
47
  #include "src/core/ext/transport/chttp2/transport/http2_settings.h"
52
48
  #include "src/core/ext/transport/chttp2/transport/http2_settings_promises.h"
53
49
  #include "src/core/ext/transport/chttp2/transport/http2_status.h"
@@ -62,19 +58,19 @@
62
58
  #include "src/core/ext/transport/chttp2/transport/stream_data_queue.h"
63
59
  #include "src/core/ext/transport/chttp2/transport/transport_common.h"
64
60
  #include "src/core/lib/channel/channel_args.h"
65
- #include "src/core/lib/debug/trace_impl.h"
66
61
  #include "src/core/lib/iomgr/closure.h"
67
62
  #include "src/core/lib/iomgr/exec_ctx.h"
63
+ #include "src/core/lib/promise/all_ok.h"
68
64
  #include "src/core/lib/promise/for_each.h"
69
65
  #include "src/core/lib/promise/if.h"
70
66
  #include "src/core/lib/promise/loop.h"
71
67
  #include "src/core/lib/promise/map.h"
72
- #include "src/core/lib/promise/match_promise.h"
73
68
  #include "src/core/lib/promise/party.h"
74
69
  #include "src/core/lib/promise/poll.h"
75
70
  #include "src/core/lib/promise/promise.h"
76
71
  #include "src/core/lib/promise/race.h"
77
72
  #include "src/core/lib/promise/sleep.h"
73
+ #include "src/core/lib/promise/status_flag.h"
78
74
  #include "src/core/lib/promise/try_seq.h"
79
75
  #include "src/core/lib/resource_quota/arena.h"
80
76
  #include "src/core/lib/resource_quota/resource_quota.h"
@@ -95,10 +91,8 @@
95
91
  #include "absl/functional/any_invocable.h"
96
92
  #include "absl/log/log.h"
97
93
  #include "absl/status/status.h"
98
- #include "absl/strings/cord.h"
99
94
  #include "absl/strings/str_cat.h"
100
95
  #include "absl/strings/string_view.h"
101
- #include "absl/types/span.h"
102
96
 
103
97
  namespace grpc_core {
104
98
  namespace http2 {
@@ -136,9 +130,10 @@ void Http2ServerTransport::AddData(channelz::DataSink sink) {
136
130
  RefCountedPtr<Party> party = nullptr;
137
131
  {
138
132
  MutexLock lock(&self->transport_mutex_);
139
- if (GPR_LIKELY(!self->is_transport_closed_)) {
140
- GRPC_DCHECK(self->general_party_ != nullptr);
141
- party = self->general_party_;
133
+ if (GPR_LIKELY(!self->shutdown_tracker_.IsShutdownInitiated(
134
+ self->transport_mutex_))) {
135
+ GRPC_DCHECK(self->transport_party_ != nullptr);
136
+ party = self->transport_party_;
142
137
  } else {
143
138
  GRPC_HTTP2_SERVER_DLOG
144
139
  << "Http2ServerTransport::AddData Transport is closed.";
@@ -170,9 +165,10 @@ void Http2ServerTransport::SpawnAddChannelzData(RefCountedPtr<Party> party,
170
165
  self->read_context_.max_new_streams_per_read_cycle())
171
166
  .Set("settings", self->settings_->ChannelzProperties())
172
167
  .Set("flow_control",
173
- self->flow_control_.stats().ChannelzProperties()));
174
- self->general_party_->ExportToChannelz("Http2ServerTransport Party",
175
- sink);
168
+ self->flow_control_.stats().ChannelzProperties())
169
+ .Set("tarpit", self->tarpit_manager_.ChannelzProperties()));
170
+ self->transport_party_->ExportToChannelz("Http2ServerTransport Party",
171
+ sink);
176
172
  GRPC_HTTP2_SERVER_DLOG
177
173
  << "Http2ServerTransport::SpawnAddChannelzData End";
178
174
  return Empty{};
@@ -186,7 +182,7 @@ void Http2ServerTransport::StartWatch(RefCountedPtr<StateWatcher> watcher) {
186
182
  MutexLock lock(&transport_mutex_);
187
183
  GRPC_CHECK(watcher_ == nullptr);
188
184
  watcher_ = std::move(watcher);
189
- if (is_transport_closed_) {
185
+ if (shutdown_tracker_.IsShutdownInitiated(transport_mutex_)) {
190
186
  // TODO(tjagtap) : [PH2][P2] : Provide better status message and
191
187
  // disconnect info here.
192
188
  NotifyStateWatcherOnDisconnectLocked(
@@ -235,7 +231,7 @@ int64_t Http2ServerTransport::TestOnlyTransportFlowControlWindow() {
235
231
 
236
232
  int64_t Http2ServerTransport::TestOnlyGetStreamFlowControlWindow(
237
233
  const uint32_t stream_id) {
238
- RefCountedPtr<Stream> stream = LookupStream(stream_id);
234
+ const RefCountedPtr<Stream> stream = LookupStream(stream_id);
239
235
  if (stream == nullptr) {
240
236
  return -1;
241
237
  }
@@ -246,7 +242,7 @@ int64_t Http2ServerTransport::TestOnlyGetStreamFlowControlWindow(
246
242
  // Endpoint Helpers
247
243
 
248
244
  auto Http2ServerTransport::EndpointWrite(SliceBuffer&& output_buf) {
249
- size_t output_buf_length = output_buf.Length();
245
+ const size_t output_buf_length = output_buf.Length();
250
246
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::EndpointWrite output_buf: "
251
247
  << output_buf_length;
252
248
 
@@ -291,7 +287,7 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(Http2DataFrame&& frame) {
291
287
 
292
288
  ping_manager_->ReceivedDataFrame();
293
289
 
294
- RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
290
+ const RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
295
291
 
296
292
  if (frame.payload.Length() > 0) {
297
293
  // DATA frames with empty payload are legitimate frames. CHTTP2 and PH2 send
@@ -408,6 +404,12 @@ Http2Status Http2ServerTransport::ProcessIncomingMetadata(T&& frame) {
408
404
  std::move(frame.payload), frame.end_headers, Http2Status::Ok(),
409
405
  settings_->acked().max_header_list_size());
410
406
  }
407
+ // TODO(tjagtap) : [PH2][P1] : Move this check as needed.
408
+ if (GPR_UNLIKELY(is_goaway_received_)) {
409
+ return Http2Status::Http2ConnectionError(
410
+ Http2ErrorCode::kProtocolError,
411
+ std::string(RFC9113::kReceivedStreamAfterGoaway));
412
+ }
411
413
 
412
414
  Http2Status append_result =
413
415
  read_context_.header_assembler().AppendFrame(frame);
@@ -459,20 +461,43 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(
459
461
  << "Http2ServerTransport::ProcessIncomingFrame(ResetStreamFrame) { "
460
462
  "stream_id="
461
463
  << frame.stream_id << ", error_code=" << frame.error_code << " }";
462
- read_context_.OnResetFrameReceived();
464
+ const ShouldSendPing should_send_ping = read_context_.OnResetFrameReceived();
465
+ if (should_send_ping.should_send_ping_on_rst_stream) {
466
+ SpawnInfallibleTransportParty("PingOnResetStream",
467
+ UntilTransportClosed(PingOnResetStream()));
468
+ }
463
469
 
464
- Http2ErrorCode error_code = FrameErrorCodeToHttp2ErrorCode(frame.error_code);
465
- absl::Status status = absl::Status(ErrorCodeToAbslStatusCode(error_code),
466
- "Reset stream frame received.");
470
+ const Http2ErrorCode error_code =
471
+ FrameErrorCodeToHttp2ErrorCode(frame.error_code);
472
+ absl::Status status =
473
+ error_code == Http2ErrorCode::kNoError
474
+ ? absl::UnavailableError("RST_STREAM frame received with no error.")
475
+ : absl::Status(ErrorCodeToAbslStatusCode(error_code),
476
+ "Reset stream frame received.");
467
477
  RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
468
478
  if (stream != nullptr) {
469
- if (status.ok()) {
470
- status =
471
- absl::UnavailableError("RST_STREAM frame received with no error.");
479
+ if (stream->IsTarpitted()) {
480
+ // If the stream is already in the Tarpit state, we do not want to process
481
+ // the RST_STREAM frame. The stream will be closed once the Tarpit timer
482
+ // expires.
483
+ GRPC_HTTP2_SERVER_DLOG
484
+ << "Http2ServerTransport::ProcessIncomingFrame(ResetStreamFrame) "
485
+ "ignoring RST_STREAM for already tarpitted stream_id="
486
+ << frame.stream_id;
487
+ } else if (tarpit_manager_.allow_tarpit()) {
488
+ // If tarpit is enabled, we will enqueue the RST_STREAM frame to the
489
+ // Tarpit manager and delay the stream reset.
490
+ StatusFlag tarpit_status = tarpit_manager_.RequestTarpitIncomingReset(
491
+ stream->GetStreamId(), std::move(status));
492
+ if (GPR_UNLIKELY(!tarpit_status.ok())) {
493
+ return Http2Status::Http2ConnectionError(
494
+ Http2ErrorCode::kInternalError, "Failed to enqueue tarpit entry");
495
+ }
496
+ } else {
497
+ // If tarpit is not enabled, we will process the RST_STREAM frame inline.
498
+ HandleStreamStateChange(*stream,
499
+ stream->OnResetReceived(std::move(status)));
472
500
  }
473
-
474
- HandleStreamStateChange(*stream,
475
- stream->OnResetReceived(std::move(status)));
476
501
  }
477
502
 
478
503
  // In case of stream error, we do not want the Read Loop to be broken. Hence
@@ -494,7 +519,7 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(
494
519
  if (!s.IsOk()) {
495
520
  return s;
496
521
  }
497
- absl::Status trigger_write_status = TriggerWriteCycle();
522
+ const absl::Status trigger_write_status = TriggerWriteCycle();
498
523
  if (!trigger_write_status.ok()) {
499
524
  return ToHttpOkOrConnError(trigger_write_status);
500
525
  }
@@ -522,11 +547,18 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(Http2PingFrame&& frame) {
522
547
  // https://www.rfc-editor.org/rfc/rfc9113.html#name-ping
523
548
  GRPC_HTTP2_SERVER_DLOG
524
549
  << "Http2ServerTransport::ProcessIncomingFrame(PingFrame) { ack="
525
- << frame.ack << ", opaque=" << frame.opaque << " }";
550
+ << frame.ack << ", opaque=" << frame.opaque << " }, "
551
+ << ping_manager_->GetDebugString(!IsPingWithoutCallsAllowed() &&
552
+ IsTransportIdle());
526
553
  if (frame.ack) {
527
554
  return ToHttpOkOrConnError(AckPing(frame.opaque));
528
555
  } else {
529
556
  read_context_.OnPingFrameReceived();
557
+ if (GPR_UNLIKELY(ping_manager_->NotifyPingAbusePolicy(
558
+ !IsPingWithoutCallsAllowed() && IsTransportIdle()))) {
559
+ return Http2Status::Http2ConnectionError(Http2ErrorCode::kEnhanceYourCalm,
560
+ "too_many_pings");
561
+ }
530
562
  if (test_only_ack_pings_) {
531
563
  ping_manager_->AddPendingPingAck(frame.opaque);
532
564
  return ToHttpOkOrConnError(TriggerWriteCycle());
@@ -550,87 +582,27 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(
550
582
  frame.error_code != static_cast<uint32_t>(Http2ErrorCode::kNoError))
551
583
  << "Received GOAWAY frame with error code: " << frame.error_code;
552
584
 
553
- // uint32_t last_stream_id = 0;
554
- // absl::Status status(ErrorCodeToAbslStatusCode(
555
- // FrameErrorCodeToHttp2ErrorCode(frame.error_code)),
556
- // frame.debug_data.empty()
557
- // ? absl::string_view("GOAWAY received")
558
- // : frame.debug_data.as_string_view());
559
- // if (GoawayManager::IsGracefulGoaway(frame)) {
560
- // const uint32_t next_stream_id = PeekNextStreamId();
561
- // last_stream_id = (next_stream_id > 1) ? next_stream_id - 2 : 0;
562
- // } else {
563
- // last_stream_id = frame.last_stream_id;
564
- // }
565
- // SetMaxAllowedStreamId(last_stream_id);
566
-
567
- // bool close_transport = false;
568
- // {
569
- // MutexLock lock(&transport_mutex_);
570
- // if (CanCloseTransportLocked()) {
571
- // close_transport = true;
572
- // GRPC_HTTP2_SERVER_DLOG <<
573
- // "Http2ServerTransport::ProcessIncomingFrame("
574
- // "GoawayFrame) "
575
- // "stream_list_ is empty";
576
- // }
577
- // }
578
-
579
- // StateWatcher::DisconnectInfo disconnect_info;
580
- // disconnect_info.reason = Transport::StateWatcher::kGoaway;
581
- // disconnect_info.http2_error_code =
582
- // static_cast<Http2ErrorCode>(frame.error_code);
583
-
584
- // // Throttle keepalive time if the server sends a GOAWAY with error code
585
- // // ENHANCE_YOUR_CALM and debug data equal to "too_many_pings". This
586
- // will
587
- // // apply to any new transport created on by any subchannel of this
588
- // channel. if (GPR_UNLIKELY(frame.error_code == static_cast<uint32_t>(
589
- // Http2ErrorCode::kEnhanceYourCalm)
590
- // &&
591
- // frame.debug_data == "too_many_pings")) {
592
- // LOG(ERROR) << ": Received a GOAWAY with error code ENHANCE_YOUR_CALM
593
- // and
594
- // "
595
- // "debug data equal to \"too_many_pings\". Current
596
- // keepalive " "time (before throttling): "
597
- // << keepalive_time_.ToString();
598
- // constexpr int max_keepalive_time_millis =
599
- // INT_MAX / KEEPALIVE_TIME_BACKOFF_MULTIPLIER;
600
- // uint64_t throttled_keepalive_time =
601
- // keepalive_time_.millis() > max_keepalive_time_millis
602
- // ? INT_MAX
603
- // : keepalive_time_.millis() *
604
- // KEEPALIVE_TIME_BACKOFF_MULTIPLIER;
605
- // if (!IsSubchannelConnectionScalingEnabled()) {
606
- // status.SetPayload(kKeepaliveThrottlingKey,
607
- // absl::Cord(std::to_string(throttled_keepalive_time)));
608
- // }
609
- // disconnect_info.keepalive_time =
610
- // Duration::Milliseconds(throttled_keepalive_time);
611
- // }
612
-
613
- // if (close_transport) {
614
- // // TODO(akshitpatel) : [PH2][P3] : Ideally the error here should be
615
- // // kNoError. However, Http2Status does not support kNoError. We
616
- // should
617
- // // revisit this and update the error code.
618
- // MaybeSpawnCloseTransport(Http2Status::Http2ConnectionError(
619
- // FrameErrorCodeToHttp2ErrorCode((
620
- // frame.error_code ==
621
- // Http2ErrorCodeToFrameErrorCode(Http2ErrorCode::kNoError)
622
- // ?
623
- // Http2ErrorCodeToFrameErrorCode(Http2ErrorCode::kInternalError)
624
- // : frame.error_code)),
625
- // frame.debug_data.empty()
626
- // ? std::string("GOAWAY received")
627
- // : std::string(frame.debug_data.as_string_view())));
628
- // }
629
-
630
- // // lie: use transient failure from the transport to indicate goaway has
631
- // been
632
- // // received.
633
- // ReportDisconnection(status, disconnect_info, "got_goaway");
585
+ is_goaway_received_ = true;
586
+
587
+ absl::Status status(ErrorCodeToAbslStatusCode(
588
+ FrameErrorCodeToHttp2ErrorCode(frame.error_code)),
589
+ frame.debug_data.empty()
590
+ ? absl::string_view("GOAWAY received")
591
+ : frame.debug_data.as_string_view());
592
+
593
+ StateWatcher::DisconnectInfo disconnect_info;
594
+ disconnect_info.reason = Transport::StateWatcher::kGoaway;
595
+ disconnect_info.http2_error_code =
596
+ FrameErrorCodeToHttp2ErrorCode(frame.error_code);
597
+
598
+ // We do not close the transport here. Instead we rely on the upper layers to
599
+ // call Orphan. Meanwhile, if the client closes the TCP connection, we will
600
+ // close transport anyway.
601
+ //
602
+ // lie: use transient failure from the transport to indicate goaway has
603
+ // been received.
604
+ ReportDisconnection(GRPC_CHANNEL_TRANSIENT_FAILURE, status, disconnect_info,
605
+ "got_goaway");
634
606
  return Http2Status::Ok();
635
607
  }
636
608
 
@@ -953,7 +925,7 @@ absl::Status Http2ServerTransport::DequeueStreamFrames(
953
925
  stream->GetStreamFlowControl(), settings_->peer()));
954
926
  stream->GetStreamFlowControl().ReportIfStalled(
955
927
  /*is_client=*/kIsClient, stream->GetStreamId(), settings_->peer());
956
- StreamDataQueue<ClientMetadataHandle>::DequeueResult result =
928
+ StreamDataQueue<ServerMetadataHandle>::DequeueResult result =
957
929
  stream->DequeueFrames(tokens, stream_flow_control_tokens,
958
930
  settings_->peer().max_frame_size(), encoder_,
959
931
  frame_sender);
@@ -1044,7 +1016,7 @@ auto Http2ServerTransport::MultiplexerLoop() {
1044
1016
  writable_stream_list_.ImmediateNext(
1045
1017
  AreTransportFlowControlTokensAvailable());
1046
1018
  if (!optional_stream.has_value()) {
1047
- GRPC_HTTP2_CLIENT_DLOG
1019
+ GRPC_HTTP2_SERVER_DLOG
1048
1020
  << "Http2ServerTransport::MultiplexerLoop "
1049
1021
  "No writable streams available ";
1050
1022
  break;
@@ -1089,8 +1061,8 @@ auto Http2ServerTransport::MultiplexerLoop() {
1089
1061
  },
1090
1062
  [this]() -> LoopCtl<absl::Status> {
1091
1063
  if (should_reset_ping_clock_) {
1092
- GRPC_HTTP2_CLIENT_DLOG
1093
- << "Http2ClientTransport::MultiplexerLoop ResetPingClock";
1064
+ GRPC_HTTP2_SERVER_DLOG
1065
+ << "Http2ServerTransport::MultiplexerLoop ResetPingClock";
1094
1066
  ping_manager_->ResetPingClock(/*is_client=*/kIsClient);
1095
1067
  should_reset_ping_clock_ = false;
1096
1068
  }
@@ -1198,8 +1170,10 @@ auto Http2ServerTransport::FlowControlPeriodicUpdateLoop() {
1198
1170
  GRPC_HTTP2_SERVER_DLOG
1199
1171
  << "Http2ServerTransport::FlowControlPeriodicUpdateLoop "
1200
1172
  "PeriodicUpdate()";
1201
- chttp2::FlowControlAction action = flow_control_.PeriodicUpdate();
1202
- bool is_action_empty = action == chttp2::FlowControlAction();
1173
+ const chttp2::FlowControlAction action =
1174
+ flow_control_.PeriodicUpdate();
1175
+ const bool is_action_empty =
1176
+ action == chttp2::FlowControlAction();
1203
1177
  // This may trigger a write cycle
1204
1178
  ActOnFlowControlAction(action, nullptr);
1205
1179
  if (is_action_empty) {
@@ -1221,7 +1195,8 @@ auto Http2ServerTransport::FlowControlPeriodicUpdateLoop() {
1221
1195
  //////////////////////////////////////////////////////////////////////////////
1222
1196
  // Stream List Operations
1223
1197
 
1224
- RefCountedPtr<Stream> Http2ServerTransport::LookupStream(uint32_t stream_id) {
1198
+ RefCountedPtr<Stream> Http2ServerTransport::LookupStream(
1199
+ const uint32_t stream_id) {
1225
1200
  MutexLock lock(&transport_mutex_);
1226
1201
  auto it = stream_list_.find(stream_id);
1227
1202
  if (it == stream_list_.end()) {
@@ -1256,6 +1231,23 @@ void Http2ServerTransport::AddToStreamList(RefCountedPtr<Stream> stream) {
1256
1231
  }
1257
1232
  }
1258
1233
 
1234
+ void Http2ServerTransport::EnqueueResetStreamFromTransportParty(
1235
+ RefCountedPtr<Stream> stream, const uint32_t reset_stream_error_code) {
1236
+ const absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1237
+ stream->EnqueueResetStream(reset_stream_error_code);
1238
+ GRPC_HTTP2_SERVER_DLOG << "Enqueued ResetStream with error code="
1239
+ << reset_stream_error_code
1240
+ << " status=" << enqueue_result.status();
1241
+ if (GPR_LIKELY(enqueue_result.ok())) {
1242
+ GRPC_UNUSED absl::Status status = MaybeAddStreamToWritableStreamList(
1243
+ std::move(stream), enqueue_result.value());
1244
+ }
1245
+ // This function could be hit multiple times for the same stream. So there is
1246
+ // a chance that we may overcount induced frames.
1247
+ // It is a bug, but not worth fixing for now.
1248
+ read_context_.OnResetFrameEnqueued(reset_stream_error_code);
1249
+ }
1250
+
1259
1251
  absl::Status Http2ServerTransport::MaybeAddStreamToWritableStreamList(
1260
1252
  RefCountedPtr<Stream> stream,
1261
1253
  const StreamDataQueue<ServerMetadataHandle>::StreamWritabilityUpdate
@@ -1331,22 +1323,51 @@ auto Http2ServerTransport::CallOutboundLoop(RefCountedPtr<Stream> stream) {
1331
1323
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CallOutboundLoop";
1332
1324
  GRPC_DCHECK(stream != nullptr);
1333
1325
 
1334
- auto send_trailing_metadata =
1335
- [this, stream](ServerMetadataHandle&& metadata) mutable {
1336
- absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1337
- stream->EnqueueTrailingMetadata(std::move(metadata));
1338
- if (GPR_UNLIKELY(!enqueue_result.ok())) {
1339
- GRPC_HTTP2_SERVER_DLOG
1340
- << "Http2ServerTransport::CallOutboundLoop Failed to enqueue "
1341
- "trailing metadata: "
1342
- << enqueue_result.status();
1343
- return enqueue_result.status();
1344
- }
1345
- GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CallOutboundLoop "
1346
- "Enqueued Trailing Metadata";
1347
- return MaybeAddStreamToWritableStreamList(std::move(stream),
1348
- enqueue_result.value());
1349
- };
1326
+ auto send_trailing_metadata = [this, stream](
1327
+ ServerMetadataHandle&& metadata) mutable {
1328
+ GRPC_DCHECK(metadata != nullptr);
1329
+ // Barrier: If stream is closed for writes or actively tarpitted, drop
1330
+ // trailing metadata.
1331
+ if (GPR_UNLIKELY(stream->IsClosedForWrites() ||
1332
+ stream->IsTarpitTimerActive())) {
1333
+ GRPC_HTTP2_SERVER_DLOG
1334
+ << "Http2ServerTransport::CallOutboundLoop ignoring trailing "
1335
+ "metadata for stream_id="
1336
+ << stream->GetStreamId()
1337
+ << " (writes_closed=" << stream->IsClosedForWrites()
1338
+ << ", tarpit_active=" << stream->IsTarpitTimerActive() << ")";
1339
+ return absl::OkStatus();
1340
+ }
1341
+
1342
+ if (metadata->get(GrpcTarPit()).has_value() &&
1343
+ tarpit_manager_.allow_tarpit()) {
1344
+ GRPC_HTTP2_SERVER_DLOG
1345
+ << "Http2ServerTransport::CallOutboundLoop Enqueuing Trailing "
1346
+ "Metadata for tarpitting, stream_id="
1347
+ << stream->GetStreamId();
1348
+ StatusFlag tarpit_status = tarpit_manager_.StartTarpitTrailers(
1349
+ stream->GetStreamId(), std::move(metadata));
1350
+ if (GPR_UNLIKELY(!tarpit_status.ok())) {
1351
+ MaybeSpawnCloseTransport(Http2Status::Http2ConnectionError(
1352
+ Http2ErrorCode::kInternalError, "Failed to enqueue tarpit entry"));
1353
+ return absl::InternalError("Failed to enqueue tarpit entry");
1354
+ }
1355
+ return absl::OkStatus();
1356
+ }
1357
+ const absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1358
+ stream->EnqueueTrailingMetadata(std::move(metadata));
1359
+ if (GPR_UNLIKELY(!enqueue_result.ok())) {
1360
+ GRPC_HTTP2_SERVER_DLOG
1361
+ << "Http2ServerTransport::CallOutboundLoop Failed to enqueue "
1362
+ "trailing metadata: "
1363
+ << enqueue_result.status();
1364
+ return enqueue_result.status();
1365
+ }
1366
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CallOutboundLoop "
1367
+ "Enqueued Trailing Metadata";
1368
+ return MaybeAddStreamToWritableStreamList(std::move(stream),
1369
+ enqueue_result.value());
1370
+ };
1350
1371
 
1351
1372
  return GRPC_LATENT_SEE_PROMISE(
1352
1373
  "Ph2CallOutboundLoop",
@@ -1380,19 +1401,20 @@ absl::Status Http2ServerTransport::InitializeStream(
1380
1401
 
1381
1402
  std::optional<RefCountedPtr<Stream>> Http2ServerTransport::MakeStream(
1382
1403
  CallInitiator&& call_initiator, const uint32_t stream_id) {
1383
- RefCountedPtr<Stream> stream =
1384
- MakeRefCounted<Stream>(call_initiator, flow_control_, stream_id,
1385
- settings_->peer().allow_true_binary_metadata());
1386
- const bool on_done_added = SetOnDone(stream);
1387
- if (!on_done_added) return std::nullopt;
1388
- return std::move(stream);
1404
+ return MakeRefCounted<Stream>(call_initiator, flow_control_, stream_id,
1405
+ settings_->peer().allow_true_binary_metadata());
1389
1406
  }
1390
1407
 
1391
1408
  Http2Status Http2ServerTransport::IncomingStream(
1392
1409
  ClientMetadataHandle&& metadata, const uint32_t stream_id) {
1410
+ if (shutdown_tracker_.IsPartyShutdownInitiated()) {
1411
+ return Http2Status::Http2ConnectionError(
1412
+ Http2ErrorCode::kRefusedStream,
1413
+ "Transport shutdown initiated (party lockdown).");
1414
+ }
1393
1415
  {
1394
1416
  MutexLock lock(&transport_mutex_);
1395
- if (is_transport_closed_) {
1417
+ if (shutdown_tracker_.IsShutdownInitiated(transport_mutex_)) {
1396
1418
  return Http2Status::Http2ConnectionError(Http2ErrorCode::kRefusedStream,
1397
1419
  "Transport is closed.");
1398
1420
  }
@@ -1432,40 +1454,67 @@ Http2Status Http2ServerTransport::IncomingStream(
1432
1454
  }
1433
1455
 
1434
1456
  void Http2ServerTransport::BeginCloseStream(
1435
- RefCountedPtr<Stream> stream, uint32_t reset_stream_error_code,
1436
- absl::Status trailing_metadata_status, DebugLocation whence) {
1457
+ RefCountedPtr<Stream> stream, const uint32_t reset_stream_error_code,
1458
+ absl::Status trailing_metadata_status, const bool tarpit,
1459
+ const bool override_tarpit, DebugLocation whence) {
1437
1460
  GRPC_DCHECK(!trailing_metadata_status.ok());
1438
- if (stream == nullptr) {
1439
- GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::BeginCloseStream stream"
1440
- "is null reset_stream_error_code="
1441
- << reset_stream_error_code
1442
- << " status=" << trailing_metadata_status;
1461
+ GRPC_DCHECK(stream != nullptr);
1462
+ // Early return if the stream is already fully closed, or currently active in
1463
+ // the tarpit lifecycle (unless override_tarpit is true). If a stream is
1464
+ // already actively being tarpitted (IsTarpitActive), subsequent close
1465
+ // requests (e.g. concurrent cancellation or timeout) must be ignored so that
1466
+ // the ongoing tarpit delay is not interrupted.
1467
+ if (stream->IsStreamClosed() ||
1468
+ (!override_tarpit && stream->IsTarpitTimerActive())) {
1469
+ GRPC_HTTP2_SERVER_DLOG
1470
+ << "Http2ServerTransport::BeginCloseStream early return for stream id: "
1471
+ << stream->GetStreamId()
1472
+ << " is_stream_closed=" << stream->IsStreamClosed()
1473
+ << " is_tarpit_active=" << stream->IsTarpitTimerActive()
1474
+ << " error_code=" << reset_stream_error_code
1475
+ << " Status=" << trailing_metadata_status << " tarpit=" << tarpit
1476
+ << " override_tarpit=" << override_tarpit
1477
+ << " location=" << whence.file() << ":" << whence.line();
1443
1478
  return;
1444
1479
  }
1445
1480
 
1446
1481
  GRPC_HTTP2_SERVER_DLOG
1447
1482
  << "Http2ServerTransport::BeginCloseStream for stream id: "
1448
1483
  << stream->GetStreamId() << " error_code=" << reset_stream_error_code
1449
- << " Status=" << trailing_metadata_status << " location=" << whence.file()
1484
+ << " Status=" << trailing_metadata_status << " tarpit=" << tarpit
1485
+ << " override_tarpit=" << override_tarpit << " location=" << whence.file()
1450
1486
  << ":" << whence.line();
1451
1487
 
1452
- // Enqueue RST_STREAM.
1453
- absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1454
- stream->EnqueueResetStream(reset_stream_error_code);
1455
- GRPC_HTTP2_SERVER_DLOG << "Enqueued ResetStream with error code="
1456
- << reset_stream_error_code
1457
- << " status=" << enqueue_result.status();
1458
- if (enqueue_result.ok()) {
1459
- GRPC_UNUSED absl::Status status =
1460
- MaybeAddStreamToWritableStreamList(stream, enqueue_result.value());
1488
+ // If tarpitting is requested and enabled (and not overridden), delegate
1489
+ // stream close to the TarpitManager. Duplicate entries will be dropped by
1490
+ // MakeTarpitDrainLoop.
1491
+ if (!override_tarpit && tarpit && tarpit_manager_.allow_tarpit()) {
1492
+ StatusFlag tarpit_status = tarpit_manager_.RequestCloseStream(
1493
+ stream->GetStreamId(), reset_stream_error_code,
1494
+ std::move(trailing_metadata_status));
1495
+ if (GPR_UNLIKELY(!tarpit_status.ok())) {
1496
+ GRPC_UNUSED const absl::Status unused = HandleError(
1497
+ std::move(stream),
1498
+ Http2Status::Http2ConnectionError(Http2ErrorCode::kInternalError,
1499
+ "Failed to enqueue tarpit entry"),
1500
+ whence);
1501
+ }
1502
+ return;
1461
1503
  }
1504
+
1505
+ // Non-tarpit path (or post-expiration reset or override): enqueue RST_STREAM
1506
+ // frame to the peer immediately and transition call handler to
1507
+ // cancelled/closed state.
1508
+ EnqueueResetStreamFromTransportParty(stream, reset_stream_error_code);
1462
1509
  HandleStreamStateChange(
1463
1510
  *stream, stream->OnInitiateReset(std::move(trailing_metadata_status)));
1464
- read_context_.OnResetFrameEnqueued(reset_stream_error_code);
1465
1511
  }
1466
1512
 
1467
- void Http2ServerTransport::HandleStreamStateChange(Stream& stream,
1468
- StreamStateChange change) {
1513
+ void Http2ServerTransport::HandleStreamStateChange(
1514
+ Stream& stream, const StreamStateChange change) {
1515
+ GRPC_HTTP2_SERVER_DLOG
1516
+ << "Http2ServerTransport::HandleStreamStateChange for stream id: "
1517
+ << stream.GetStreamId() << " change: " << change.DebugString();
1469
1518
  if (change.reads_became_closed) {
1470
1519
  // If a stream is closing for reads and was actively waiting for a
1471
1520
  // continuation frame, parse the buffered HEADER/CONTINUATION frames
@@ -1503,6 +1552,10 @@ void Http2ServerTransport::CleanupStream(Stream& stream) {
1503
1552
  should_close = true;
1504
1553
  }
1505
1554
  }
1555
+ // Subtract any positive announced window delta of closed stream from the
1556
+ // transport flow control.
1557
+ stream.GetStreamFlowControl().OnStreamClosed();
1558
+
1506
1559
  if (should_close) {
1507
1560
  MaybeSpawnCloseTransport(Http2Status::AbslConnectionError(
1508
1561
  absl::StatusCode::kUnavailable, "Graceful shutdown complete."));
@@ -1560,7 +1613,7 @@ void Http2ServerTransport::MaybeSpawnDelayedPing(
1560
1613
  }
1561
1614
  }
1562
1615
 
1563
- absl::Status Http2ServerTransport::AckPing(uint64_t opaque_data) {
1616
+ absl::Status Http2ServerTransport::AckPing(const uint64_t opaque_data) {
1564
1617
  // It is possible that the PingRatePolicy may decide to not send a ping
1565
1618
  // request (in cases like the number of inflight pings is too high).
1566
1619
  // When this happens, it becomes important to ensure that if a ping ack
@@ -1618,6 +1671,112 @@ auto Http2ServerTransport::SpawnGracefulGoawayPromise(Slice&& debug_data) {
1618
1671
  });
1619
1672
  }
1620
1673
 
1674
+ //////////////////////////////////////////////////////////////////////////////
1675
+ // Tarpit
1676
+
1677
+ void Http2ServerTransport::ActOnTarpitEntries(
1678
+ std::vector<TarpitEntry>&& entries) {
1679
+ for (TarpitEntry& entry : entries) {
1680
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::ActOnTarpitEntries "
1681
+ << " DebugString=" << entry.DebugString();
1682
+ RefCountedPtr<Stream> stream = LookupStream(entry.GetStreamId());
1683
+ if (stream == nullptr || stream->IsStreamClosed()) {
1684
+ GRPC_HTTP2_SERVER_DLOG
1685
+ << "Http2ServerTransport::ActOnTarpitEntries ignoring expired entry "
1686
+ "for closed/reclaimed stream_id="
1687
+ << entry.GetStreamId();
1688
+ continue;
1689
+ }
1690
+ stream->SetTarpitCompleted();
1691
+ if (entry.IsIncomingReset()) {
1692
+ std::optional<TarpitEntry::IncomingResetPayload> reset =
1693
+ entry.TakeIncomingResetPayload();
1694
+ GRPC_DCHECK(reset.has_value());
1695
+ HandleStreamStateChange(
1696
+ *stream, stream->OnResetReceived(std::move(reset->status)));
1697
+ } else if (entry.IsOutgoingReset()) {
1698
+ std::optional<TarpitEntry::OutgoingResetPayload> reset =
1699
+ entry.TakeOutgoingResetPayload();
1700
+ GRPC_DCHECK(reset.has_value());
1701
+ BeginCloseStream(std::move(stream), reset->http2_error_code,
1702
+ std::move(reset->trailing_metadata_status),
1703
+ /*tarpit=*/false);
1704
+ } else if (entry.IsOutgoingTrailingMetadata()) {
1705
+ std::optional<TarpitEntry::OutgoingTrailingMetadataPayload> trailers =
1706
+ entry.TakeOutgoingTrailingMetadataPayload();
1707
+ GRPC_DCHECK(trailers.has_value());
1708
+ const absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1709
+ stream->EnqueueTrailingMetadata(std::move(trailers->metadata));
1710
+ if (GPR_LIKELY(enqueue_result.ok())) {
1711
+ GRPC_UNUSED const absl::Status status =
1712
+ MaybeAddStreamToWritableStreamList(std::move(stream),
1713
+ *enqueue_result);
1714
+ } else {
1715
+ HandleStreamStateChange(*stream,
1716
+ stream->ForceClose(absl::InternalError(
1717
+ "Failed to enqueue trailing metadata")));
1718
+ }
1719
+ } else {
1720
+ GRPC_DCHECK(false)
1721
+ << "Http2ServerTransport::ActOnTarpitEntries unhandled tarpit entry "
1722
+ "type for stream_id="
1723
+ << entry.GetStreamId() << " entry=" << entry.DebugString();
1724
+ }
1725
+ }
1726
+ }
1727
+
1728
+ auto Http2ServerTransport::MakeTarpitTimerLoop() {
1729
+ return Loop([this]() {
1730
+ return TrySeq(
1731
+ tarpit_manager_.WaitForTimerExpire(),
1732
+ [this]() {
1733
+ ActOnTarpitEntries(tarpit_manager_.OnTimerExpired());
1734
+ return absl::OkStatus();
1735
+ },
1736
+ []() -> LoopCtl<absl::Status> { return Continue(); });
1737
+ });
1738
+ }
1739
+
1740
+ auto Http2ServerTransport::MakeTarpitDrainLoop() {
1741
+ return AllOk<absl::Status>(
1742
+ Loop([this]() {
1743
+ return Map(
1744
+ tarpit_manager_.NextMessage(),
1745
+ [this](auto&& result) -> LoopCtl<absl::Status> {
1746
+ if (GPR_UNLIKELY(!result.ok())) {
1747
+ return absl::CancelledError("Tarpit drain loop cancelled");
1748
+ }
1749
+ TarpitEntry msg = std::move(*result.value());
1750
+ const RefCountedPtr<Stream> stream =
1751
+ LookupStream(msg.GetStreamId());
1752
+ if (GPR_UNLIKELY(stream == nullptr || stream->IsStreamClosed())) {
1753
+ GRPC_HTTP2_SERVER_DLOG
1754
+ << "Http2ServerTransport::MakeTarpitDrainLoop ignoring "
1755
+ "tarpit entry for already closed stream_id="
1756
+ << msg.GetStreamId();
1757
+ return Continue();
1758
+ }
1759
+ if (GPR_UNLIKELY(stream->IsTarpitted())) {
1760
+ GRPC_HTTP2_SERVER_DLOG
1761
+ << "Http2ServerTransport::MakeTarpitDrainLoop ignoring "
1762
+ "duplicate tarpit entry for stream_id="
1763
+ << msg.GetStreamId();
1764
+ return Continue();
1765
+ }
1766
+ GRPC_HTTP2_SERVER_DLOG
1767
+ << "Http2ServerTransport::MakeTarpitDrainLoop enqueuing "
1768
+ "tarpit entry for stream_id="
1769
+ << msg.GetStreamId();
1770
+
1771
+ HandleStreamStateChange(*stream,
1772
+ tarpit_manager_.OnTarpit(*stream));
1773
+ tarpit_manager_.AddToQueue(std::move(msg));
1774
+ return Continue();
1775
+ });
1776
+ }),
1777
+ MakeTarpitTimerLoop());
1778
+ }
1779
+
1621
1780
  //////////////////////////////////////////////////////////////////////////////
1622
1781
  // Error Path and Close Path
1623
1782
 
@@ -1631,7 +1790,7 @@ absl::Status Http2ServerTransport::HandleError(RefCountedPtr<Stream> stream,
1631
1790
  << " status=" << status.DebugString()
1632
1791
  << " location=" << whence.file() << ":"
1633
1792
  << whence.line();
1634
- Http2Status::Http2ErrorType error_type = status.GetType();
1793
+ const Http2Status::Http2ErrorType error_type = status.GetType();
1635
1794
  GRPC_DCHECK(error_type != Http2Status::Http2ErrorType::kOk);
1636
1795
 
1637
1796
  if (error_type == Http2Status::Http2ErrorType::kConnectionError) {
@@ -1640,11 +1799,12 @@ absl::Status Http2ServerTransport::HandleError(RefCountedPtr<Stream> stream,
1640
1799
  MaybeSpawnCloseTransport(std::move(status), whence);
1641
1800
  return absl_status;
1642
1801
  } else if (error_type == Http2Status::Http2ErrorType::kStreamError) {
1643
- uint32_t reset_stream_error_code =
1802
+ const uint32_t reset_stream_error_code =
1644
1803
  Http2ErrorCodeToFrameErrorCode(status.GetStreamErrorCode());
1645
1804
  if (stream != nullptr) {
1646
1805
  BeginCloseStream(std::move(stream), reset_stream_error_code,
1647
- status.GetAbslStreamError(), whence);
1806
+ status.GetAbslStreamError(), /*tarpit=*/true,
1807
+ /*override_tarpit=*/false, whence);
1648
1808
  }
1649
1809
  return absl::OkStatus();
1650
1810
  }
@@ -1652,6 +1812,64 @@ absl::Status Http2ServerTransport::HandleError(RefCountedPtr<Stream> stream,
1652
1812
  GPR_UNREACHABLE_CODE(return absl::InternalError("Invalid error type"));
1653
1813
  }
1654
1814
 
1815
+ void Http2ServerTransport::CloseAllActiveStreams(
1816
+ absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>>&& stream_list,
1817
+ const Http2Status& http2_status, DebugLocation whence) {
1818
+ // Close all the streams that are still active on the transport.
1819
+ absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>> stream_list_2;
1820
+ {
1821
+ MutexLock lock(&transport_mutex_);
1822
+ stream_list_2 = std::move(stream_list_);
1823
+ stream_list_.clear();
1824
+ }
1825
+
1826
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CloseAllActiveStreams "
1827
+ "Cleaning up call stacks";
1828
+
1829
+ auto close_streams =
1830
+ [&](const absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>>& list) {
1831
+ for (const auto& pair : list) {
1832
+ RefCountedPtr<Stream> stream = pair.second;
1833
+ BeginCloseStream(std::move(stream),
1834
+ Http2ErrorCodeToFrameErrorCode(
1835
+ http2_status.GetConnectionErrorCode()),
1836
+ http2_status.GetAbslConnectionError(),
1837
+ /*tarpit=*/false, /*override_tarpit=*/true, whence);
1838
+ }
1839
+ };
1840
+
1841
+ close_streams(stream_list); // Snapshot 1
1842
+ close_streams(stream_list_2); // Snapshot 2
1843
+ }
1844
+
1845
+ auto Http2ServerTransport::CloseTransportFactory(
1846
+ absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>> stream_list,
1847
+ Http2Status http2_status, DebugLocation whence) {
1848
+ return [self = RefAsSubclass<Http2ServerTransport>(),
1849
+ stream_list = std::move(stream_list),
1850
+ http2_status = std::move(http2_status), whence]() mutable {
1851
+ self->shutdown_tracker_.InitiatePartyShutdown();
1852
+ self->security_frame_handler_->OnTransportClosed();
1853
+
1854
+ self->tarpit_manager_.Shutdown();
1855
+ self->CloseAllActiveStreams(std::move(stream_list), http2_status, whence);
1856
+
1857
+ // Sleep for kGoawaySendTimeoutSeconds before closing the transport to
1858
+ // let write buffers drain.
1859
+ return Map(
1860
+ Race(AssertResultType<absl::Status>(self->goaway_manager_.RequestGoaway(
1861
+ http2_status.GetConnectionErrorCode(),
1862
+ Slice::FromCopiedString(std::string(
1863
+ http2_status.GetAbslConnectionError().message())),
1864
+ self->last_incoming_stream_id_, /*immediate=*/true)),
1865
+ Sleep(Duration::Seconds(kGoawaySendTimeoutSeconds))),
1866
+ [self](absl::Status) mutable {
1867
+ self->CloseTransport();
1868
+ return Empty{};
1869
+ });
1870
+ };
1871
+ }
1872
+
1655
1873
  void Http2ServerTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1656
1874
  DebugLocation whence) {
1657
1875
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::MaybeSpawnCloseTransport "
@@ -1661,13 +1879,13 @@ void Http2ServerTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1661
1879
  << whence.line();
1662
1880
 
1663
1881
  ReleasableMutexLock lock(&transport_mutex_);
1664
- if (is_transport_closed_) {
1882
+ if (shutdown_tracker_.IsShutdownInitiated(transport_mutex_)) {
1665
1883
  lock.Release();
1666
1884
  return;
1667
1885
  }
1668
1886
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::MaybeSpawnCloseTransport "
1669
1887
  "Initiating transport close";
1670
- is_transport_closed_ = true;
1888
+ shutdown_tracker_.InitiateShutdown(transport_mutex_);
1671
1889
  absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>> stream_list =
1672
1890
  std::move(stream_list_);
1673
1891
  stream_list_.clear();
@@ -1677,44 +1895,14 @@ void Http2ServerTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1677
1895
  lock.Release();
1678
1896
 
1679
1897
  SpawnInfallibleTransportParty(
1680
- "CloseTransport",
1681
- [self = RefAsSubclass<Http2ServerTransport>(),
1682
- stream_list = std::move(stream_list),
1683
- http2_status = std::move(http2_status), whence]() mutable {
1684
- self->security_frame_handler_->OnTransportClosed();
1685
- GRPC_HTTP2_SERVER_DLOG
1686
- << "Http2ServerTransport::MaybeSpawnCloseTransport "
1687
- "Cleaning up call stacks";
1688
- // Clean up the call stacks for all active streams.
1689
- for (const auto& pair : stream_list) {
1690
- RefCountedPtr<Stream> stream = pair.second;
1691
- self->BeginCloseStream(std::move(stream),
1692
- Http2ErrorCodeToFrameErrorCode(
1693
- http2_status.GetConnectionErrorCode()),
1694
- http2_status.GetAbslConnectionError(), whence);
1695
- }
1696
-
1697
- // Sleep for kGoawaySendTimeoutSeconds before closing the transport to
1698
- // let write buffers drain.
1699
- return Map(
1700
- Race(AssertResultType<absl::Status>(
1701
- self->goaway_manager_.RequestGoaway(
1702
- http2_status.GetConnectionErrorCode(),
1703
- Slice::FromCopiedString(std::string(
1704
- http2_status.GetAbslConnectionError().message())),
1705
- self->last_incoming_stream_id_, /*immediate=*/true)),
1706
- Sleep(Duration::Seconds(kGoawaySendTimeoutSeconds))),
1707
- [self](auto) mutable {
1708
- self->CloseTransport();
1709
- return Empty{};
1710
- });
1711
- });
1898
+ "CloseTransport", CloseTransportFactory(std::move(stream_list),
1899
+ std::move(http2_status), whence));
1712
1900
  }
1713
1901
 
1714
1902
  void Http2ServerTransport::CloseTransport() {
1715
1903
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CloseTransport";
1716
1904
 
1717
- transport_closed_latch_.Set();
1905
+ shutdown_tracker_.MarkShutdownComplete();
1718
1906
  settings_->HandleTransportShutdown(event_engine_.get());
1719
1907
 
1720
1908
  if (on_close_callback_ != nullptr) {
@@ -1722,7 +1910,7 @@ void Http2ServerTransport::CloseTransport() {
1722
1910
  on_close_callback_ = nullptr;
1723
1911
  }
1724
1912
 
1725
- general_party_.reset();
1913
+ transport_party_.reset();
1726
1914
  }
1727
1915
 
1728
1916
  //////////////////////////////////////////////////////////////////////////////
@@ -1745,65 +1933,6 @@ void Http2ServerTransport::ReportDisconnectionLocked(
1745
1933
  NotifyStateWatcherOnDisconnectLocked(status, disconnect_info);
1746
1934
  }
1747
1935
 
1748
- bool Http2ServerTransport::SetOnDone(RefCountedPtr<Stream> stream) {
1749
- // TODO(akshitpatel) : [PH2][P0] : Implement this.
1750
- return stream->GetCallInitiator().OnDone(
1751
- [self = RefAsSubclass<Http2ServerTransport>(),
1752
- stream = std::move(stream)](GRPC_UNUSED bool cancelled) mutable {});
1753
- }
1754
- // return call_handler.OnDone([self = RefAsSubclass<Http2ServerTransport>(),
1755
- // stream =
1756
- // std::move(stream)](bool cancelled) mutable
1757
- // {
1758
- // GRPC_HTTP2_SERVER_DLOG << "PH2: Client call " << self.get()
1759
- // << " id=" << stream->GetStreamId()
1760
- // << " done: cancelled=" << cancelled;
1761
- // absl::StatusOr<StreamWritabilityUpdate> enqueue_result;
1762
- // GRPC_HTTP2_SERVER_DLOG << "PH2: Client call " << self.get()
1763
- // << " id=" << stream->GetStreamId()
1764
- // << " done: stream=" << stream.get()
1765
- // << " cancelled=" << cancelled;
1766
-
1767
- // // If the stream is already closed for writes, then we don't need to
1768
- // // enqueue the reset stream or the half closed frame.
1769
- // if (stream->IsClosedForWrites()) {
1770
- // GRPC_HTTP2_SERVER_DLOG << "PH2: Client call " << self.get()
1771
- // << " id=" << stream->GetStreamId()
1772
- // << " done: stream already closed for writes";
1773
- // return;
1774
- // }
1775
-
1776
- // if (cancelled) {
1777
- // // In most of the cases, EnqueueResetStream would be a no-op as
1778
- // // BeginCloseStream would have already enqueued the reset stream.
1779
- // // Currently only Aborts from application will actually enqueue
1780
- // // the reset stream here.
1781
- // enqueue_result = stream->EnqueueResetStream(
1782
- // static_cast<uint32_t>(Http2ErrorCode::kCancel));
1783
- // GRPC_HTTP2_SERVER_DLOG << "Enqueued ResetStream with error code="
1784
- // <<
1785
- // static_cast<uint32_t>(Http2ErrorCode::kCancel)
1786
- // << " status=" << enqueue_result.status();
1787
- // } else {
1788
- // enqueue_result = stream->EnqueueHalfClosed();
1789
- // GRPC_HTTP2_SERVER_DLOG << "Enqueued HalfClosed with result="
1790
- // << enqueue_result.status();
1791
- // }
1792
-
1793
- // if (GPR_LIKELY(enqueue_result.ok())) {
1794
- // GRPC_HTTP2_SERVER_DLOG
1795
- // << "Http2ServerTransport::SetOnDone "
1796
- // "MaybeAddStreamToWritableStreamList for stream= "
1797
- // << stream->GetStreamId() << " enqueue_result={became_writable="
1798
- // << enqueue_result.value().became_writable << ", priority="
1799
- // << static_cast<uint8_t>(enqueue_result.value().priority) << "}";
1800
- // GRPC_UNUSED absl::Status status =
1801
- // self->MaybeAddStreamToWritableStreamList(std::move(stream),
1802
- // enqueue_result.value());
1803
- // }
1804
- // });
1805
- // }
1806
-
1807
1936
  void Http2ServerTransport::ReadChannelArgs(const ChannelArgs& channel_args,
1808
1937
  TransportChannelArgs& args) {
1809
1938
  http2::ReadChannelArgs(channel_args, args, settings_->mutable_local(),
@@ -1916,10 +2045,13 @@ Http2ServerTransport::Http2ServerTransport(
1916
2045
  settings_(MakeRefCounted<SettingsPromiseManager>(
1917
2046
  kIsClient, std::move(on_receive_settings))),
1918
2047
  on_close_callback_(on_close_callback),
2048
+ is_goaway_received_(false),
1919
2049
  should_reset_ping_clock_(false),
1920
2050
  read_context_(MaxNewStreamsPerRead(channel_args), endpoint_, kIsClient,
1921
- GetMaxSecurityFrameSize(channel_args)),
2051
+ GetMaxSecurityFrameSize(channel_args),
2052
+ GetPingOnRstStreamPercent(channel_args, kIsClient)),
1922
2053
  transport_write_context_(kIsClient),
2054
+ last_incoming_stream_id_(0),
1923
2055
  ping_manager_(std::nullopt),
1924
2056
  keepalive_manager_(std::nullopt),
1925
2057
  goaway_manager_(GoawayInterfaceImpl::Make(this)),
@@ -1931,19 +2063,20 @@ Http2ServerTransport::Http2ServerTransport(
1931
2063
  channel_args.GetBool(GRPC_ARG_HTTP2_BDP_PROBE).value_or(true),
1932
2064
  &memory_owner_),
1933
2065
  security_frame_handler_(MakeRefCounted<SecurityFrameHandler>()),
1934
- ztrace_collector_(std::make_shared<PromiseHttp2ZTraceCollector>()) {
2066
+ ztrace_collector_(std::make_shared<PromiseHttp2ZTraceCollector>()),
2067
+ tarpit_manager_(channel_args) {
1935
2068
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport Constructor Begin";
1936
2069
 
1937
2070
  // Initialize the general party and write party.
1938
2071
  RefCountedPtr<Arena> party_arena = SimpleArenaAllocator(0)->MakeArena();
1939
2072
  party_arena->SetContext<EventEngine>(event_engine_.get());
1940
- general_party_ = Party::Make(std::move(party_arena));
2073
+ transport_party_ = Party::Make(std::move(party_arena));
1941
2074
 
1942
2075
  InitLocalSettings(settings_->mutable_local(), /*is_client=*/kIsClient);
1943
2076
  TransportChannelArgs args;
1944
2077
  ReadChannelArgs(channel_args, args);
1945
2078
 
1946
- ping_manager_.emplace(channel_args, args.ping_timeout,
2079
+ ping_manager_.emplace(channel_args, kIsClient, args.ping_timeout,
1947
2080
  PingSystemInterfaceImpl::Make(this), event_engine_);
1948
2081
 
1949
2082
  // The keepalive loop is only spawned if the keepalive time is not infinity.
@@ -1963,7 +2096,7 @@ Http2ServerTransport::Http2ServerTransport(
1963
2096
  Http2ServerTransport::~Http2ServerTransport() {
1964
2097
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport Destructor Begin";
1965
2098
  // GRPC_DCHECK(stream_list_.empty());
1966
- // GRPC_DCHECK(general_party_ == nullptr);
2099
+ // GRPC_DCHECK(transport_party_ == nullptr);
1967
2100
  // memory_owner_.Reset();
1968
2101
 
1969
2102
  // TODO(akshitpatel) : [PH2][P0][Close] : Remove call to
@@ -2036,10 +2169,6 @@ void Http2ServerTransport::SpawnTransportLoops() {
2036
2169
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::SpawnTransportLoops Begin";
2037
2170
  MaybeSpawnKeepaliveLoop();
2038
2171
 
2039
- // SpawnGuardedTransportParty(
2040
- // "FlowControlPeriodicUpdateLoop",
2041
- // UntilTransportClosed(FlowControlPeriodicUpdateLoop()));
2042
-
2043
2172
  if (!TriggerWriteCycleOrHandleError()) {
2044
2173
  return;
2045
2174
  }
@@ -2049,6 +2178,10 @@ void Http2ServerTransport::SpawnTransportLoops() {
2049
2178
  SpawnGuardedTransportParty("ReadLoop", UntilTransportClosed(ReadLoop()));
2050
2179
  SpawnGuardedTransportParty("MultiplexerLoop",
2051
2180
  UntilTransportClosed(MultiplexerLoop()));
2181
+ if (tarpit_manager_.allow_tarpit()) {
2182
+ SpawnGuardedTransportParty("TarpitDrainLoop",
2183
+ UntilTransportClosed(MakeTarpitDrainLoop()));
2184
+ }
2052
2185
 
2053
2186
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::SpawnTransportLoops End";
2054
2187
  }