grpc 1.75.0.pre1 → 1.76.0.pre1

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 (387) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +18 -5
  3. data/include/grpc/credentials.h +21 -5
  4. data/src/core/call/call_filters.cc +4 -4
  5. data/src/core/call/call_filters.h +36 -36
  6. data/src/core/call/call_spine.h +27 -27
  7. data/src/core/call/client_call.cc +6 -5
  8. data/src/core/call/filter_fusion.h +5 -5
  9. data/src/core/call/metadata_batch.h +3 -3
  10. data/src/core/call/security_context.cc +1 -1
  11. data/src/core/call/server_call.cc +4 -4
  12. data/src/core/call/server_call.h +1 -1
  13. data/src/core/channelz/channelz.cc +12 -18
  14. data/src/core/channelz/channelz.h +32 -16
  15. data/src/core/channelz/channelz_registry.h +11 -0
  16. data/src/core/channelz/property_list.cc +18 -0
  17. data/src/core/channelz/property_list.h +10 -1
  18. data/src/core/channelz/text_encode.cc +66 -0
  19. data/src/core/channelz/text_encode.h +29 -0
  20. data/src/core/channelz/v2tov1/convert.cc +11 -0
  21. data/src/core/channelz/v2tov1/legacy_api.cc +15 -8
  22. data/src/core/channelz/ztrace_collector.h +247 -86
  23. data/src/core/client_channel/backup_poller.cc +5 -6
  24. data/src/core/client_channel/client_channel.cc +20 -13
  25. data/src/core/client_channel/client_channel_filter.cc +53 -45
  26. data/src/core/client_channel/client_channel_filter.h +2 -2
  27. data/src/core/client_channel/client_channel_internal.h +3 -4
  28. data/src/core/client_channel/config_selector.h +3 -3
  29. data/src/core/client_channel/dynamic_filters.cc +3 -3
  30. data/src/core/client_channel/global_subchannel_pool.cc +0 -37
  31. data/src/core/client_channel/global_subchannel_pool.h +0 -27
  32. data/src/core/client_channel/load_balanced_call_destination.cc +7 -7
  33. data/src/core/client_channel/local_subchannel_pool.cc +4 -4
  34. data/src/core/client_channel/retry_filter.h +3 -3
  35. data/src/core/client_channel/retry_filter_legacy_call_data.cc +5 -5
  36. data/src/core/client_channel/subchannel.cc +8 -8
  37. data/src/core/client_channel/subchannel_stream_client.cc +4 -4
  38. data/src/core/config/config_vars.cc +30 -1
  39. data/src/core/config/config_vars.h +21 -0
  40. data/src/core/config/core_configuration.cc +5 -5
  41. data/src/core/config/core_configuration.h +7 -7
  42. data/src/core/config/load_config.cc +12 -0
  43. data/src/core/config/load_config.h +2 -0
  44. data/src/core/credentials/call/call_credentials.h +2 -2
  45. data/src/core/credentials/call/call_creds_util.cc +4 -3
  46. data/src/core/credentials/call/composite/composite_call_credentials.cc +4 -4
  47. data/src/core/credentials/call/external/aws_external_account_credentials.cc +3 -3
  48. data/src/core/credentials/call/external/external_account_credentials.cc +1 -1
  49. data/src/core/credentials/call/external/url_external_account_credentials.cc +1 -1
  50. data/src/core/credentials/call/iam/iam_credentials.cc +4 -4
  51. data/src/core/credentials/call/jwt/json_token.cc +3 -3
  52. data/src/core/credentials/call/jwt/jwt_credentials.cc +2 -2
  53. data/src/core/credentials/call/jwt/jwt_verifier.cc +14 -13
  54. data/src/core/credentials/call/oauth2/oauth2_credentials.cc +20 -12
  55. data/src/core/credentials/call/plugin/plugin_credentials.cc +2 -2
  56. data/src/core/credentials/transport/alts/alts_credentials.cc +4 -4
  57. data/src/core/credentials/transport/alts/alts_security_connector.cc +14 -12
  58. data/src/core/credentials/transport/alts/grpc_alts_credentials_client_options.cc +22 -2
  59. data/src/core/credentials/transport/alts/grpc_alts_credentials_options.cc +10 -1
  60. data/src/core/credentials/transport/alts/grpc_alts_credentials_options.h +31 -0
  61. data/src/core/credentials/transport/alts/grpc_alts_credentials_server_options.cc +8 -3
  62. data/src/core/credentials/transport/composite/composite_channel_credentials.cc +5 -5
  63. data/src/core/credentials/transport/fake/fake_security_connector.cc +2 -2
  64. data/src/core/credentials/transport/google_default/google_default_credentials.cc +78 -28
  65. data/src/core/credentials/transport/insecure/insecure_security_connector.cc +3 -3
  66. data/src/core/credentials/transport/local/local_security_connector.cc +8 -8
  67. data/src/core/credentials/transport/security_connector.cc +5 -5
  68. data/src/core/credentials/transport/ssl/ssl_credentials.cc +12 -12
  69. data/src/core/credentials/transport/ssl/ssl_credentials.h +2 -2
  70. data/src/core/credentials/transport/ssl/ssl_security_connector.cc +3 -3
  71. data/src/core/credentials/transport/tls/certificate_provider_registry.cc +2 -2
  72. data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.cc +24 -24
  73. data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.cc +5 -5
  74. data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.h +2 -2
  75. data/src/core/credentials/transport/tls/grpc_tls_certificate_verifier.cc +2 -2
  76. data/src/core/credentials/transport/tls/grpc_tls_certificate_verifier.h +2 -2
  77. data/src/core/credentials/transport/tls/grpc_tls_credentials_options.cc +17 -17
  78. data/src/core/credentials/transport/tls/ssl_utils.cc +14 -9
  79. data/src/core/credentials/transport/tls/tls_credentials.cc +2 -2
  80. data/src/core/credentials/transport/tls/tls_security_connector.cc +11 -11
  81. data/src/core/credentials/transport/transport_credentials.cc +2 -2
  82. data/src/core/credentials/transport/transport_credentials.h +2 -2
  83. data/src/core/credentials/transport/xds/xds_credentials.cc +5 -5
  84. data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc +2 -0
  85. data/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.cc +1 -1
  86. data/src/core/ext/filters/http/message_compress/compression_filter.cc +8 -8
  87. data/src/core/ext/filters/http/message_compress/compression_filter.h +3 -3
  88. data/src/core/ext/filters/stateful_session/stateful_session_filter.cc +7 -7
  89. data/src/core/ext/transport/chttp2/alpn/alpn.cc +2 -2
  90. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +10 -9
  91. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +10 -7
  92. data/src/core/ext/transport/chttp2/transport/bin_decoder.cc +5 -5
  93. data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +6 -6
  94. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +96 -88
  95. data/src/core/ext/transport/chttp2/transport/flow_control.cc +3 -3
  96. data/src/core/ext/transport/chttp2/transport/flow_control.h +12 -7
  97. data/src/core/ext/transport/chttp2/transport/flow_control_manager.h +60 -0
  98. data/src/core/ext/transport/chttp2/transport/frame.cc +32 -10
  99. data/src/core/ext/transport/chttp2/transport/frame.h +16 -2
  100. data/src/core/ext/transport/chttp2/transport/frame_data.cc +2 -2
  101. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +4 -4
  102. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +2 -2
  103. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +2 -2
  104. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +3 -3
  105. data/src/core/ext/transport/chttp2/transport/header_assembler.h +28 -12
  106. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +2 -2
  107. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +4 -2
  108. data/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc +8 -8
  109. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +2 -2
  110. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +2 -2
  111. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +27 -27
  112. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +2 -3
  113. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +4 -4
  114. data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +543 -366
  115. data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +198 -277
  116. data/src/core/ext/transport/chttp2/transport/http2_settings_manager.cc +3 -0
  117. data/src/core/ext/transport/chttp2/transport/http2_settings_manager.h +11 -0
  118. data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +179 -0
  119. data/src/core/ext/transport/chttp2/transport/http2_transport.cc +51 -23
  120. data/src/core/ext/transport/chttp2/transport/http2_transport.h +13 -6
  121. data/src/core/ext/transport/chttp2/transport/http2_ztrace_collector.h +115 -71
  122. data/src/core/ext/transport/chttp2/transport/internal.h +6 -14
  123. data/src/core/ext/transport/chttp2/transport/message_assembler.h +7 -7
  124. data/src/core/ext/transport/chttp2/transport/parsing.cc +17 -15
  125. data/src/core/ext/transport/chttp2/transport/ping_callbacks.cc +2 -2
  126. data/src/core/ext/transport/chttp2/transport/ping_promise.cc +62 -26
  127. data/src/core/ext/transport/chttp2/transport/ping_promise.h +58 -22
  128. data/src/core/ext/transport/chttp2/transport/stream.h +207 -0
  129. data/src/core/ext/transport/chttp2/transport/stream_data_queue.h +328 -187
  130. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +7 -7
  131. data/src/core/ext/transport/chttp2/transport/transport_common.cc +17 -1
  132. data/src/core/ext/transport/chttp2/transport/transport_common.h +52 -0
  133. data/src/core/ext/transport/chttp2/transport/varint.h +2 -2
  134. data/src/core/ext/transport/chttp2/transport/writable_streams.h +181 -79
  135. data/src/core/ext/transport/chttp2/transport/write_size_policy.cc +2 -2
  136. data/src/core/ext/transport/chttp2/transport/writing.cc +3 -3
  137. data/src/core/ext/transport/inproc/inproc_transport.cc +1 -1
  138. data/src/core/ext/transport/inproc/legacy_inproc_transport.cc +3 -3
  139. data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb.h +740 -0
  140. data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb_minitable.c +218 -0
  141. data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb_minitable.h +46 -0
  142. data/src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb.h +87 -55
  143. data/src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb_minitable.c +23 -21
  144. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/channelz.upbdefs.c +80 -0
  145. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/channelz.upbdefs.h +47 -0
  146. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/service.upbdefs.c +129 -0
  147. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/service.upbdefs.h +72 -0
  148. data/src/core/filter/auth/server_auth_filter.cc +2 -2
  149. data/src/core/handshaker/handshaker.cc +3 -3
  150. data/src/core/handshaker/http_connect/http_proxy_mapper.cc +2 -2
  151. data/src/core/handshaker/security/legacy_secure_endpoint.cc +2 -2
  152. data/src/core/handshaker/security/pipelined_secure_endpoint.cc +31 -8
  153. data/src/core/handshaker/security/secure_endpoint.cc +16 -6
  154. data/src/core/handshaker/security/security_handshaker.cc +3 -3
  155. data/src/core/handshaker/tcp_connect/tcp_connect_handshaker.cc +2 -2
  156. data/src/core/lib/channel/channel_stack.cc +8 -5
  157. data/src/core/lib/channel/channel_stack.h +3 -0
  158. data/src/core/lib/channel/channel_stack_builder_impl.cc +1 -0
  159. data/src/core/lib/channel/connected_channel.cc +2 -2
  160. data/src/core/lib/channel/promise_based_filter.cc +69 -64
  161. data/src/core/lib/channel/promise_based_filter.h +16 -15
  162. data/src/core/lib/compression/compression_internal.cc +2 -2
  163. data/src/core/lib/compression/message_compress.cc +7 -7
  164. data/src/core/lib/event_engine/ares_resolver.cc +22 -20
  165. data/src/core/lib/event_engine/cf_engine/cf_engine.cc +2 -2
  166. data/src/core/lib/event_engine/cf_engine/dns_service_resolver.cc +2 -2
  167. data/src/core/lib/event_engine/cf_engine/dns_service_resolver.h +2 -2
  168. data/src/core/lib/event_engine/extensions/channelz.h +2 -2
  169. data/src/core/lib/event_engine/extensions/supports_fd.h +5 -5
  170. data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc +8 -8
  171. data/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc +10 -10
  172. data/src/core/lib/event_engine/posix_engine/lockfree_event.cc +2 -2
  173. data/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +23 -22
  174. data/src/core/lib/event_engine/posix_engine/posix_endpoint.h +11 -11
  175. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +168 -170
  176. data/src/core/lib/event_engine/posix_engine/posix_engine.h +33 -54
  177. data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +4 -3
  178. data/src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc +5 -5
  179. data/src/core/lib/event_engine/posix_engine/posix_interface.h +1 -1
  180. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc +1 -1
  181. data/src/core/lib/event_engine/posix_engine/timer_manager.cc +3 -3
  182. data/src/core/lib/event_engine/resolved_address.cc +3 -3
  183. data/src/core/lib/event_engine/shim.cc +8 -11
  184. data/src/core/lib/event_engine/shim.h +2 -1
  185. data/src/core/lib/event_engine/slice.cc +2 -2
  186. data/src/core/lib/event_engine/tcp_socket_utils.cc +11 -11
  187. data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc +7 -7
  188. data/src/core/lib/event_engine/windows/grpc_polled_fd_windows.cc +31 -31
  189. data/src/core/lib/event_engine/windows/iocp.cc +10 -10
  190. data/src/core/lib/event_engine/windows/win_socket.cc +6 -6
  191. data/src/core/lib/event_engine/windows/windows_endpoint.cc +11 -11
  192. data/src/core/lib/event_engine/windows/windows_engine.cc +16 -14
  193. data/src/core/lib/event_engine/windows/windows_listener.cc +7 -7
  194. data/src/core/lib/experiments/experiments.cc +105 -18
  195. data/src/core/lib/experiments/experiments.h +43 -11
  196. data/src/core/lib/iomgr/call_combiner.cc +3 -3
  197. data/src/core/lib/iomgr/endpoint_cfstream.cc +6 -6
  198. data/src/core/lib/iomgr/endpoint_pair_posix.cc +5 -5
  199. data/src/core/lib/iomgr/endpoint_pair_windows.cc +15 -14
  200. data/src/core/lib/iomgr/ev_epoll1_linux.cc +15 -15
  201. data/src/core/lib/iomgr/ev_poll_posix.cc +11 -11
  202. data/src/core/lib/iomgr/event_engine_shims/endpoint.cc +5 -4
  203. data/src/core/lib/iomgr/event_engine_shims/endpoint.h +1 -1
  204. data/src/core/lib/iomgr/iocp_windows.cc +8 -8
  205. data/src/core/lib/iomgr/iomgr_windows.cc +3 -3
  206. data/src/core/lib/iomgr/lockfree_event.cc +2 -2
  207. data/src/core/lib/iomgr/polling_entity.cc +3 -3
  208. data/src/core/lib/iomgr/socket_utils_common_posix.cc +2 -2
  209. data/src/core/lib/iomgr/socket_windows.cc +4 -4
  210. data/src/core/lib/iomgr/tcp_client_posix.cc +4 -4
  211. data/src/core/lib/iomgr/tcp_client_windows.cc +4 -4
  212. data/src/core/lib/iomgr/tcp_posix.cc +42 -42
  213. data/src/core/lib/iomgr/tcp_server.cc +5 -0
  214. data/src/core/lib/iomgr/tcp_server.h +7 -0
  215. data/src/core/lib/iomgr/tcp_server_posix.cc +47 -27
  216. data/src/core/lib/iomgr/tcp_server_utils_posix.h +3 -0
  217. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +5 -5
  218. data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +2 -2
  219. data/src/core/lib/iomgr/tcp_server_windows.cc +68 -29
  220. data/src/core/lib/iomgr/tcp_windows.cc +7 -7
  221. data/src/core/lib/iomgr/timer_generic.cc +2 -2
  222. data/src/core/lib/iomgr/timer_manager.cc +2 -2
  223. data/src/core/lib/iomgr/unix_sockets_posix.cc +2 -2
  224. data/src/core/lib/iomgr/unix_sockets_posix_noop.cc +2 -2
  225. data/src/core/lib/promise/activity.cc +2 -2
  226. data/src/core/lib/promise/activity.h +6 -6
  227. data/src/core/lib/promise/context.h +2 -2
  228. data/src/core/lib/promise/detail/join_state.h +9 -9
  229. data/src/core/lib/promise/detail/seq_state.h +13 -13
  230. data/src/core/lib/promise/detail/status.h +2 -2
  231. data/src/core/lib/promise/for_each.h +5 -5
  232. data/src/core/lib/promise/interceptor_list.h +2 -2
  233. data/src/core/lib/promise/latch.h +7 -7
  234. data/src/core/lib/promise/mpsc.cc +26 -26
  235. data/src/core/lib/promise/mpsc.h +2 -2
  236. data/src/core/lib/promise/observable.h +4 -4
  237. data/src/core/lib/promise/party.cc +32 -25
  238. data/src/core/lib/promise/party.h +16 -19
  239. data/src/core/lib/promise/pipe.h +15 -15
  240. data/src/core/lib/promise/poll.h +5 -4
  241. data/src/core/lib/promise/promise.h +0 -2
  242. data/src/core/lib/promise/sleep.cc +3 -1
  243. data/src/core/lib/promise/status_flag.h +7 -7
  244. data/src/core/lib/promise/try_join.h +2 -2
  245. data/src/core/lib/promise/try_seq.h +2 -2
  246. data/src/core/lib/resource_quota/arena.h +15 -2
  247. data/src/core/lib/resource_quota/connection_quota.cc +9 -7
  248. data/src/core/lib/resource_quota/memory_quota.cc +45 -24
  249. data/src/core/lib/resource_quota/memory_quota.h +48 -16
  250. data/src/core/lib/resource_quota/telemetry.h +54 -0
  251. data/src/core/lib/resource_quota/thread_quota.cc +2 -2
  252. data/src/core/lib/resource_tracker/resource_tracker.cc +33 -0
  253. data/src/core/lib/resource_tracker/resource_tracker.h +46 -0
  254. data/src/core/lib/security/authorization/audit_logging.cc +5 -5
  255. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +2 -2
  256. data/src/core/lib/security/authorization/stdout_logger.cc +3 -3
  257. data/src/core/lib/surface/byte_buffer_reader.cc +2 -2
  258. data/src/core/lib/surface/call.cc +16 -14
  259. data/src/core/lib/surface/call.h +1 -1
  260. data/src/core/lib/surface/call_utils.cc +2 -2
  261. data/src/core/lib/surface/call_utils.h +2 -2
  262. data/src/core/lib/surface/channel.cc +4 -4
  263. data/src/core/lib/surface/channel_create.cc +10 -6
  264. data/src/core/lib/surface/channel_init.cc +80 -23
  265. data/src/core/lib/surface/channel_init.h +26 -11
  266. data/src/core/lib/surface/completion_queue.cc +17 -16
  267. data/src/core/lib/surface/completion_queue_factory.cc +7 -7
  268. data/src/core/lib/surface/connection_context.h +45 -2
  269. data/src/core/lib/surface/filter_stack_call.cc +12 -23
  270. data/src/core/lib/surface/filter_stack_call.h +3 -4
  271. data/src/core/lib/surface/legacy_channel.cc +7 -7
  272. data/src/core/lib/surface/validate_metadata.h +2 -2
  273. data/src/core/lib/surface/version.cc +2 -2
  274. data/src/core/lib/transport/bdp_estimator.cc +2 -2
  275. data/src/core/lib/transport/bdp_estimator.h +3 -3
  276. data/src/core/lib/transport/promise_endpoint.cc +3 -3
  277. data/src/core/lib/transport/promise_endpoint.h +8 -8
  278. data/src/core/lib/transport/timeout_encoding.cc +4 -4
  279. data/src/core/load_balancing/child_policy_handler.cc +4 -4
  280. data/src/core/load_balancing/endpoint_list.cc +2 -2
  281. data/src/core/load_balancing/grpclb/grpclb.cc +24 -24
  282. data/src/core/load_balancing/health_check_client.cc +4 -4
  283. data/src/core/load_balancing/health_check_client_internal.h +2 -2
  284. data/src/core/load_balancing/lb_policy_registry.cc +2 -2
  285. data/src/core/load_balancing/oob_backend_metric.cc +4 -4
  286. data/src/core/load_balancing/oob_backend_metric_internal.h +2 -2
  287. data/src/core/load_balancing/outlier_detection/outlier_detection.cc +2 -2
  288. data/src/core/load_balancing/pick_first/pick_first.cc +14 -14
  289. data/src/core/load_balancing/priority/priority.cc +23 -24
  290. data/src/core/load_balancing/ring_hash/ring_hash.cc +3 -3
  291. data/src/core/load_balancing/rls/rls.cc +13 -13
  292. data/src/core/load_balancing/round_robin/round_robin.cc +9 -9
  293. data/src/core/load_balancing/weighted_round_robin/static_stride_scheduler.cc +3 -3
  294. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +33 -26
  295. data/src/core/load_balancing/weighted_target/weighted_target.cc +5 -5
  296. data/src/core/load_balancing/xds/cds.cc +76 -32
  297. data/src/core/load_balancing/xds/xds_cluster_impl.cc +3 -3
  298. data/src/core/load_balancing/xds/xds_override_host.cc +4 -4
  299. data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +2 -2
  300. data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +33 -33
  301. data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc +10 -10
  302. data/src/core/resolver/dns/dns_resolver_plugin.cc +6 -3
  303. data/src/core/resolver/dns/event_engine/event_engine_client_channel_resolver.cc +2 -2
  304. data/src/core/resolver/endpoint_addresses.cc +3 -3
  305. data/src/core/resolver/endpoint_addresses.h +3 -0
  306. data/src/core/resolver/fake/fake_resolver.cc +2 -2
  307. data/src/core/resolver/google_c2p/google_c2p_resolver.cc +41 -54
  308. data/src/core/resolver/polling_resolver.cc +3 -3
  309. data/src/core/resolver/resolver_registry.cc +5 -4
  310. data/src/core/resolver/xds/xds_dependency_manager.cc +5 -5
  311. data/src/core/resolver/xds/xds_resolver.cc +9 -9
  312. data/src/core/server/server.cc +38 -38
  313. data/src/core/server/server_call_tracer_filter.h +4 -4
  314. data/src/core/server/server_config_selector_filter.cc +2 -2
  315. data/src/core/server/xds_server_config_fetcher.cc +9 -8
  316. data/src/core/service_config/service_config_impl.h +2 -2
  317. data/src/core/telemetry/call_tracer.cc +39 -49
  318. data/src/core/telemetry/call_tracer.h +199 -22
  319. data/src/core/telemetry/histogram.h +205 -0
  320. data/src/core/telemetry/instrument.cc +719 -0
  321. data/src/core/telemetry/instrument.h +932 -0
  322. data/src/core/telemetry/metrics.cc +13 -5
  323. data/src/core/telemetry/metrics.h +3 -1
  324. data/src/core/telemetry/stats_data.cc +0 -19
  325. data/src/core/telemetry/stats_data.h +0 -19
  326. data/src/core/transport/auth_context.cc +2 -2
  327. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +78 -45
  328. data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +1 -0
  329. data/src/core/tsi/alts/handshaker/alts_shared_resource.cc +3 -3
  330. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +39 -31
  331. data/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +3 -3
  332. data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc +3 -3
  333. data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc +7 -7
  334. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +3 -3
  335. data/src/core/tsi/fake_transport_security.cc +4 -4
  336. data/src/core/tsi/ssl/key_logging/ssl_key_logging.cc +4 -4
  337. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +9 -9
  338. data/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc +3 -3
  339. data/src/core/tsi/ssl_transport_security.cc +26 -25
  340. data/src/core/tsi/ssl_transport_security_utils.cc +9 -9
  341. data/src/core/util/chunked_vector.h +4 -4
  342. data/src/core/util/event_log.cc +2 -2
  343. data/src/core/util/gcp_metadata_query.cc +2 -2
  344. data/src/core/util/grpc_check.cc +22 -0
  345. data/src/core/util/grpc_check.h +103 -0
  346. data/src/core/util/http_client/httpcli.cc +3 -3
  347. data/src/core/util/http_client/parser.cc +4 -4
  348. data/src/core/util/latent_see.h +7 -4
  349. data/src/core/util/lru_cache.h +4 -4
  350. data/src/core/util/memory_usage.h +16 -0
  351. data/src/core/util/posix/directory_reader.cc +3 -2
  352. data/src/core/util/posix/sync.cc +24 -24
  353. data/src/core/util/postmortem_emit.cc +52 -0
  354. data/src/core/util/postmortem_emit.h +30 -0
  355. data/src/core/util/ref_counted_ptr.h +5 -0
  356. data/src/core/util/trie_lookup.h +170 -0
  357. data/src/core/util/unique_ptr_with_bitset.h +5 -5
  358. data/src/core/xds/grpc/xds_bootstrap_grpc.h +6 -1
  359. data/src/core/xds/grpc/xds_certificate_provider.cc +3 -3
  360. data/src/core/xds/grpc/xds_client_grpc.cc +34 -15
  361. data/src/core/xds/grpc/xds_client_grpc.h +4 -1
  362. data/src/core/xds/grpc/xds_cluster_parser.cc +2 -2
  363. data/src/core/xds/grpc/xds_cluster_specifier_plugin.cc +2 -2
  364. data/src/core/xds/grpc/xds_endpoint_parser.cc +2 -2
  365. data/src/core/xds/grpc/xds_http_filter_registry.cc +4 -3
  366. data/src/core/xds/grpc/xds_listener_parser.cc +3 -3
  367. data/src/core/xds/grpc/xds_matcher.cc +277 -0
  368. data/src/core/xds/grpc/xds_matcher.h +432 -0
  369. data/src/core/xds/grpc/xds_matcher_action.cc +47 -0
  370. data/src/core/xds/grpc/xds_matcher_action.h +48 -0
  371. data/src/core/xds/grpc/xds_matcher_context.cc +29 -0
  372. data/src/core/xds/grpc/xds_matcher_context.h +46 -0
  373. data/src/core/xds/grpc/xds_matcher_input.cc +79 -0
  374. data/src/core/xds/grpc/xds_matcher_input.h +105 -0
  375. data/src/core/xds/grpc/xds_matcher_parse.cc +356 -0
  376. data/src/core/xds/grpc/xds_matcher_parse.h +39 -0
  377. data/src/core/xds/grpc/xds_metadata.cc +4 -3
  378. data/src/core/xds/grpc/xds_route_config_parser.cc +6 -6
  379. data/src/core/xds/grpc/xds_routing.cc +3 -3
  380. data/src/core/xds/grpc/xds_transport_grpc.cc +10 -10
  381. data/src/core/xds/xds_client/lrs_client.cc +6 -6
  382. data/src/core/xds/xds_client/xds_client.cc +9 -9
  383. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +2 -2
  384. data/src/ruby/lib/grpc/version.rb +1 -1
  385. data/third_party/abseil-cpp/absl/container/internal/node_slot_policy.h +95 -0
  386. data/third_party/abseil-cpp/absl/container/node_hash_map.h +687 -0
  387. metadata +37 -2
@@ -26,19 +26,23 @@
26
26
  #include <optional>
27
27
  #include <utility>
28
28
 
29
- #include "absl/log/check.h"
30
29
  #include "absl/log/log.h"
31
30
  #include "absl/status/status.h"
31
+ #include "absl/strings/string_view.h"
32
32
  #include "src/core/call/call_spine.h"
33
33
  #include "src/core/call/message.h"
34
34
  #include "src/core/call/metadata_batch.h"
35
+ #include "src/core/ext/transport/chttp2/transport/flow_control.h"
36
+ #include "src/core/ext/transport/chttp2/transport/flow_control_manager.h"
35
37
  #include "src/core/ext/transport/chttp2/transport/frame.h"
36
38
  #include "src/core/ext/transport/chttp2/transport/header_assembler.h"
37
39
  #include "src/core/ext/transport/chttp2/transport/http2_settings.h"
38
40
  #include "src/core/ext/transport/chttp2/transport/http2_settings_manager.h"
39
41
  #include "src/core/ext/transport/chttp2/transport/http2_status.h"
42
+ #include "src/core/ext/transport/chttp2/transport/http2_ztrace_collector.h"
40
43
  #include "src/core/ext/transport/chttp2/transport/internal_channel_arg_names.h"
41
44
  #include "src/core/ext/transport/chttp2/transport/message_assembler.h"
45
+ #include "src/core/ext/transport/chttp2/transport/stream_data_queue.h"
42
46
  #include "src/core/ext/transport/chttp2/transport/transport_common.h"
43
47
  #include "src/core/lib/channel/channel_args.h"
44
48
  #include "src/core/lib/debug/trace.h"
@@ -51,10 +55,12 @@
51
55
  #include "src/core/lib/promise/promise.h"
52
56
  #include "src/core/lib/promise/try_seq.h"
53
57
  #include "src/core/lib/resource_quota/arena.h"
58
+ #include "src/core/lib/resource_quota/resource_quota.h"
54
59
  #include "src/core/lib/slice/slice.h"
55
60
  #include "src/core/lib/slice/slice_buffer.h"
56
61
  #include "src/core/lib/transport/promise_endpoint.h"
57
62
  #include "src/core/lib/transport/transport.h"
63
+ #include "src/core/util/grpc_check.h"
58
64
  #include "src/core/util/ref_counted_ptr.h"
59
65
  #include "src/core/util/sync.h"
60
66
 
@@ -62,6 +68,7 @@ namespace grpc_core {
62
68
  namespace http2 {
63
69
 
64
70
  using grpc_event_engine::experimental::EventEngine;
71
+ using EnqueueResult = StreamDataQueue<ClientMetadataHandle>::EnqueueResult;
65
72
 
66
73
  // Experimental : This is just the initial skeleton of class
67
74
  // and it is functions. The code will be written iteratively.
@@ -84,8 +91,9 @@ void Http2ClientTransport::PerformOp(grpc_transport_op* op) {
84
91
  StopConnectivityWatch(op->stop_connectivity_watch);
85
92
  did_stuff = true;
86
93
  }
87
- CHECK(!op->set_accept_stream) << "Set_accept_stream not supported on clients";
88
- DCHECK(did_stuff) << "Unimplemented transport perform op ";
94
+ GRPC_CHECK(!op->set_accept_stream)
95
+ << "Set_accept_stream not supported on clients";
96
+ GRPC_DCHECK(did_stuff) << "Unimplemented transport perform op ";
89
97
 
90
98
  ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, absl::OkStatus());
91
99
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport PerformOp End";
@@ -219,8 +227,7 @@ Http2Status Http2ClientTransport::ProcessHttp2HeaderFrame(
219
227
  << ", payload=" << frame.payload.JoinIntoString() << " }";
220
228
  ping_manager_.ReceivedDataFrame();
221
229
 
222
- RefCountedPtr<Http2ClientTransport::Stream> stream =
223
- LookupStream(frame.stream_id);
230
+ RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
224
231
  if (stream == nullptr) {
225
232
  // TODO(tjagtap) : [PH2][P3] : Implement this.
226
233
  // RFC9113 : The identifier of a newly established stream MUST be
@@ -254,19 +261,20 @@ Http2Status Http2ClientTransport::ProcessHttp2HeaderFrame(
254
261
  HeaderAssembler& assembler = stream->header_assembler;
255
262
  Http2Status append_result = assembler.AppendHeaderFrame(std::move(frame));
256
263
  if (append_result.IsOk()) {
257
- return ProcessMetadata(stream->stream_id, assembler, stream->call,
258
- stream->did_push_initial_metadata,
259
- stream->did_push_trailing_metadata);
264
+ return ProcessMetadata(stream);
260
265
  }
261
266
  return append_result;
262
267
  }
263
268
 
264
269
  Http2Status Http2ClientTransport::ProcessMetadata(
265
- uint32_t stream_id, HeaderAssembler& assembler, CallHandler& call,
266
- bool& did_push_initial_metadata, bool& did_push_trailing_metadata) {
270
+ RefCountedPtr<Stream> stream) {
271
+ const uint32_t stream_id = stream->GetStreamId();
272
+ HeaderAssembler& assembler = stream->header_assembler;
273
+ CallHandler call = stream->call;
274
+
267
275
  GRPC_HTTP2_CLIENT_DLOG << "Http2Transport ProcessMetadata";
268
276
  if (assembler.IsReady()) {
269
- ValueOrHttp2Status<Arena::PoolPtr<grpc_metadata_batch>> read_result =
277
+ ValueOrHttp2Status<ServerMetadataHandle> read_result =
270
278
  assembler.ReadMetadata(parser_, !incoming_header_end_stream_,
271
279
  /*is_client=*/true,
272
280
  /*max_header_list_size_soft_limit=*/
@@ -274,27 +282,21 @@ Http2Status Http2ClientTransport::ProcessMetadata(
274
282
  /*max_header_list_size_hard_limit=*/
275
283
  settings_.acked().max_header_list_size());
276
284
  if (read_result.IsOk()) {
277
- Arena::PoolPtr<grpc_metadata_batch> metadata =
278
- TakeValue(std::move(read_result));
285
+ ServerMetadataHandle metadata = TakeValue(std::move(read_result));
279
286
  if (incoming_header_end_stream_) {
280
287
  // TODO(tjagtap) : [PH2][P1] : Is this the right way to differentiate
281
288
  // between initial and trailing metadata?
282
289
  GRPC_HTTP2_CLIENT_DLOG
283
290
  << "Http2Transport ProcessMetadata SpawnPushServerTrailingMetadata";
284
- did_push_trailing_metadata = true;
285
- call.SpawnPushServerTrailingMetadata(std::move(metadata));
286
- CloseStream(stream_id, absl::OkStatus(),
287
- CloseStreamArgs{
288
- /*close_reads=*/true,
289
- /*close_writes=*/true,
290
- /*send_rst_stream=*/false,
291
- /*should_not_push_trailers=*/true,
292
- });
293
-
291
+ stream->MarkHalfClosedRemote();
292
+ BeginCloseStream(
293
+ stream_id,
294
+ Http2ErrorCodeToRstFrameErrorCode(Http2ErrorCode::kNoError),
295
+ std::move(metadata));
294
296
  } else {
295
297
  GRPC_HTTP2_CLIENT_DLOG
296
298
  << "Http2Transport ProcessMetadata SpawnPushServerInitialMetadata";
297
- did_push_initial_metadata = true;
299
+ stream->did_push_initial_metadata = true;
298
300
  call.SpawnPushServerInitialMetadata(std::move(metadata));
299
301
  }
300
302
  return Http2Status::Ok();
@@ -313,16 +315,12 @@ Http2Status Http2ClientTransport::ProcessHttp2RstStreamFrame(
313
315
  << "Http2Transport ProcessHttp2RstStreamFrame { stream_id="
314
316
  << frame.stream_id << ", error_code=" << frame.error_code << " }";
315
317
  Http2ErrorCode error_code =
316
- Http2ErrorCodeFromRstFrameErrorCode(frame.error_code);
317
- CloseStream(frame.stream_id,
318
- absl::Status((ErrorCodeToAbslStatusCode(error_code)),
319
- "Reset stream frame received."),
320
- CloseStreamArgs{
321
- /*close_reads=*/true,
322
- /*close_writes=*/true,
323
- /*send_rst_stream=*/false,
324
- /*push_trailing_metadata=*/true,
325
- });
318
+ RstFrameErrorCodeToHttp2ErrorCode(frame.error_code);
319
+ absl::Status status = absl::Status(ErrorCodeToAbslStatusCode(error_code),
320
+ "Reset stream frame received.");
321
+ BeginCloseStream(frame.stream_id, /*reset_stream_error_code=*/std::nullopt,
322
+ CancelledServerMetadataFromStatus(status));
323
+
326
324
  // In case of stream error, we do not want the Read Loop to be broken. Hence
327
325
  // returning an ok status.
328
326
  return Http2Status::Ok();
@@ -343,6 +341,9 @@ Http2Status Http2ClientTransport::ProcessHttp2SettingsFrame(
343
341
  on_receive_settings_ = nullptr;
344
342
  }
345
343
 
344
+ // TODO(tjagtap) : [PH2][P2] Decide later if we want this only for AckLastSend
345
+ // or does any other operation also need this lock.
346
+ MutexLock lock(&transport_mutex_);
346
347
  if (!frame.ack) {
347
348
  // Check if the received settings have legal values
348
349
  Http2Status status = ValidateSettingsValues(frame.settings);
@@ -353,9 +354,15 @@ Http2Status Http2ClientTransport::ProcessHttp2SettingsFrame(
353
354
  // Apply the new settings
354
355
  // Quickly send the ACK to the peer once the settings are applied
355
356
  } else {
356
- // TODO(tjagtap) : [PH2][P1]
357
- // Stop the setting timeout promise
358
- // Update the ACKed setting data structure
357
+ // Process the SETTINGS ACK Frame
358
+ if (settings_.AckLastSend()) {
359
+ transport_settings_.OnSettingsAckReceived();
360
+ } else {
361
+ // TODO(tjagtap) [PH2][P4] : The RFC does not say anything about what
362
+ // should happen if we receive an unsolicited SETTINGS ACK. Decide if we
363
+ // want to respond with any error or just proceed.
364
+ LOG(ERROR) << "Settings ack received without sending settings";
365
+ }
359
366
  }
360
367
 
361
368
  return Http2Status::Ok();
@@ -378,7 +385,7 @@ auto Http2ClientTransport::ProcessHttp2PingFrame(Http2PingFrame frame) {
378
385
  // writes.
379
386
  // RFC9113: PING responses SHOULD be given higher priority than any
380
387
  // other frame.
381
- self->pending_ping_acks_.push_back(opaque);
388
+ self->ping_manager_.AddPendingPingAck(opaque);
382
389
  // TODO(akshitpatel) : [PH2][P2] : This is done assuming that the other
383
390
  // ProcessFrame promises may return stream or connection failures. If
384
391
  // this does not turn out to be true, consider returning absl::Status
@@ -416,6 +423,18 @@ Http2Status Http2ClientTransport::ProcessHttp2WindowUpdateFrame(
416
423
  << "Http2Transport ProcessHttp2WindowUpdateFrame Promise { "
417
424
  " stream_id="
418
425
  << frame.stream_id << ", increment=" << frame.increment << "}";
426
+ if (frame.stream_id != 0) {
427
+ RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
428
+ if (stream != nullptr) {
429
+ chttp2::StreamFlowControl::OutgoingUpdateContext fc_update(
430
+ &stream->flow_control);
431
+ fc_update.RecvUpdate(frame.increment);
432
+ }
433
+ } else {
434
+ chttp2::TransportFlowControl::OutgoingUpdateContext fc_update(
435
+ &flow_control_);
436
+ fc_update.RecvUpdate(frame.increment);
437
+ }
419
438
  return Http2Status::Ok();
420
439
  }
421
440
 
@@ -448,9 +467,7 @@ Http2Status Http2ClientTransport::ProcessHttp2ContinuationFrame(
448
467
  HeaderAssembler& assember = stream->header_assembler;
449
468
  Http2Status result = assember.AppendContinuationFrame(std::move(frame));
450
469
  if (result.IsOk()) {
451
- return ProcessMetadata(stream->stream_id, assember, stream->call,
452
- stream->did_push_initial_metadata,
453
- stream->did_push_trailing_metadata);
470
+ return ProcessMetadata(stream);
454
471
  }
455
472
  return result;
456
473
  }
@@ -544,8 +561,10 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
544
561
  /*incoming_header_stream_id*/ self->incoming_header_stream_id_,
545
562
  /*current_frame_header*/ header);
546
563
 
547
- if (!status.IsOk()) {
548
- return self->HandleError(std::move(status));
564
+ if (GPR_UNLIKELY(!status.IsOk())) {
565
+ GRPC_DCHECK(status.GetType() ==
566
+ Http2Status::Http2ErrorType::kConnectionError);
567
+ return self->HandleError(std::nullopt, std::move(status));
549
568
  }
550
569
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ReadAndProcessOneFrame "
551
570
  "Validated Frame Header:"
@@ -570,6 +589,7 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
570
589
  ParseFramePayload(self->current_frame_header_, std::move(payload));
571
590
  if (!frame.IsOk()) {
572
591
  return self->HandleError(
592
+ self->current_frame_header_.stream_id,
573
593
  ValueOrHttp2Status<Http2Frame>::TakeStatus(std::move(frame)));
574
594
  }
575
595
  return TakeValue(std::move(frame));
@@ -578,14 +598,15 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
578
598
  GRPC_UNUSED Http2Frame frame) {
579
599
  GRPC_HTTP2_CLIENT_DLOG
580
600
  << "Http2ClientTransport ReadAndProcessOneFrame ProcessOneFrame";
581
- return AssertResultType<absl::Status>(
582
- Map(self->ProcessOneFrame(std::move(frame)),
583
- [self](Http2Status status) {
584
- if (!status.IsOk()) {
585
- return self->HandleError(std::move(status));
586
- }
587
- return absl::OkStatus();
588
- }));
601
+ return AssertResultType<absl::Status>(Map(
602
+ self->ProcessOneFrame(std::move(frame)),
603
+ [self](Http2Status status) {
604
+ if (!status.IsOk()) {
605
+ return self->HandleError(self->current_frame_header_.stream_id,
606
+ std::move(status));
607
+ }
608
+ return absl::OkStatus();
609
+ }));
589
610
  }));
590
611
  }
591
612
 
@@ -608,189 +629,281 @@ auto Http2ClientTransport::OnReadLoopEnded() {
608
629
  [self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
609
630
  GRPC_HTTP2_CLIENT_DLOG
610
631
  << "Http2ClientTransport OnReadLoopEnded Promise Status=" << status;
611
- GRPC_UNUSED absl::Status error =
612
- self->HandleError(Http2Status::AbslConnectionError(
613
- status.code(), std::string(status.message())));
632
+ GRPC_UNUSED absl::Status error = self->HandleError(
633
+ std::nullopt, Http2Status::AbslConnectionError(
634
+ status.code(), std::string(status.message())));
614
635
  };
615
636
  }
616
637
 
638
+ // Equivalent to grpc_chttp2_act_on_flowctl_action in chttp2_transport.cc
639
+ // TODO(tjagtap) : [PH2][P4] : grpc_chttp2_act_on_flowctl_action has a "reason"
640
+ // parameter which looks like it would be really helpful for debugging. Add that
641
+ void Http2ClientTransport::ActOnFlowControlAction(
642
+ const chttp2::FlowControlAction& action, const uint32_t stream_id) {
643
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::ActOnFlowControlAction";
644
+ if (action.send_stream_update() != kNoActionNeeded) {
645
+ GRPC_DCHECK_GT(stream_id, 0u);
646
+ RefCountedPtr<Stream> stream = LookupStream(stream_id);
647
+ if (GPR_LIKELY(stream != nullptr)) {
648
+ const HttpStreamState state = stream->GetStreamState();
649
+ if (state != HttpStreamState::kHalfClosedRemote &&
650
+ state != HttpStreamState::kClosed) {
651
+ // Stream is not remotely closed, so sending a WINDOW_UPDATE is
652
+ // potentially useful.
653
+ // TODO(tjagtap) : [PH2][P1] Plumb with flow control
654
+ }
655
+ } else {
656
+ GRPC_HTTP2_CLIENT_DLOG
657
+ << "Http2ClientTransport ActOnFlowControlAction stream is null";
658
+ }
659
+ }
660
+
661
+ if (action.send_transport_update() != kNoActionNeeded) {
662
+ // TODO(tjagtap) : [PH2][P1] Plumb with flow control
663
+ }
664
+
665
+ // TODO(tjagtap) : [PH2][P1] Plumb
666
+ // enable_preferred_rx_crypto_frame_advertisement with settings
667
+ ActOnFlowControlActionSettings(
668
+ action, settings_.mutable_local(),
669
+ /*enable_preferred_rx_crypto_frame_advertisement=*/true);
670
+
671
+ if (action.AnyUpdateImmediately()) {
672
+ TriggerWriteCycle();
673
+ }
674
+ }
675
+
617
676
  ///////////////////////////////////////////////////////////////////////////////
618
677
  // Write Related Promises and Promise Factories
619
678
 
620
- auto Http2ClientTransport::WriteFromQueue() {
621
- GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteFromQueue Factory";
622
- return TrySeq(
623
- outgoing_frames_.NextBatch(128),
624
- [self = RefAsSubclass<Http2ClientTransport>()](
625
- std::vector<Http2Frame> frames) {
626
- SliceBuffer output_buf;
627
- if (self->is_first_write_) {
628
- GRPC_HTTP2_CLIENT_DLOG
629
- << "Http2ClientTransport Write GRPC_CHTTP2_CLIENT_CONNECT_STRING";
630
- output_buf.Append(Slice(grpc_slice_from_copied_string(
631
- GRPC_CHTTP2_CLIENT_CONNECT_STRING)));
632
- self->is_first_write_ = false;
633
- }
634
- Serialize(absl::Span<Http2Frame>(frames), output_buf);
635
- uint64_t buffer_length = output_buf.Length();
636
- GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteFromQueue Promise";
637
- return If(
638
- buffer_length > 0,
639
- [self, output_buffer = std::move(output_buf)]() mutable {
640
- self->bytes_sent_in_last_write_ = true;
641
- return self->endpoint_.Write(std::move(output_buffer),
642
- PromiseEndpoint::WriteArgs{});
643
- },
644
- [] { return absl::OkStatus(); });
679
+ auto Http2ClientTransport::WriteControlFrames() {
680
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteControlFrames Factory";
681
+ SliceBuffer output_buf;
682
+ if (is_first_write_) {
683
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Write "
684
+ "GRPC_CHTTP2_CLIENT_CONNECT_STRING";
685
+ output_buf.Append(Slice(
686
+ grpc_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)));
687
+ is_first_write_ = false;
688
+ }
689
+ MaybeGetSettingsFrame(output_buf);
690
+ ping_manager_.MaybeGetSerializedPingFrames(output_buf,
691
+ NextAllowedPingInterval());
692
+ const uint64_t buffer_length = output_buf.Length();
693
+ return If(
694
+ buffer_length > 0,
695
+ [self = RefAsSubclass<Http2ClientTransport>(),
696
+ output_buf = std::move(output_buf), buffer_length]() mutable {
697
+ GRPC_HTTP2_CLIENT_DLOG
698
+ << "Http2ClientTransport WriteControlFrames Writing buffer of size "
699
+ << buffer_length << " to endpoint";
700
+ return self->endpoint_.Write(std::move(output_buf),
701
+ PromiseEndpoint::WriteArgs{});
702
+ },
703
+ [self = RefAsSubclass<Http2ClientTransport>(), buffer_length] {
704
+ self->ztrace_collector_->Append(
705
+ PromiseEndpointWriteTrace{buffer_length});
706
+ return absl::OkStatus();
645
707
  });
646
708
  }
647
709
 
648
- auto Http2ClientTransport::WriteLoop() {
649
- GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteLoop Factory";
650
- return AssertResultType<absl::Status>(
651
- Loop([self = RefAsSubclass<Http2ClientTransport>()]() {
652
- // TODO(akshitpatel) : [PH2][P1] : Once a common SliceBuffer is used, we
653
- // can move bytes_sent_in_last_write_ to be a local variable.
654
- self->bytes_sent_in_last_write_ = false;
655
- return TrySeq(
656
- // TODO(akshitpatel) : [PH2][P1] : WriteFromQueue may write settings
657
- // acks as well. This will break the call to ResetPingClock as it
658
- // only needs to be called on writing Data/Header/WindowUpdate
659
- // frames. Possible fixes: Either WriteFromQueue iterates over all
660
- // the frames and figures out the types of frames needed (this may
661
- // anyways be needed to check that we do not send frames for closed
662
- // streams) or we have flags to indicate the types of frame that are
663
- // enqueued.
664
- self->WriteFromQueue(), [self] { return self->MaybeSendPing(); },
665
- [self] { return self->MaybeSendPingAcks(); },
666
- [self]() -> LoopCtl<absl::Status> {
667
- // If any Header/Data/WindowUpdate frame was sent in the last
668
- // write, reset the ping clock.
669
- if (self->bytes_sent_in_last_write_) {
670
- self->ping_manager_.ResetPingClock(/*is_client=*/true);
671
- }
672
- GRPC_HTTP2_CLIENT_DLOG
673
- << "Http2ClientTransport WriteLoop Continue";
674
- return Continue();
675
- });
676
- }));
710
+ void Http2ClientTransport::NotifyControlFramesWriteDone() {
711
+ // Notify Control modules that we have sent the frames.
712
+ // All notifications are expected to be synchronous.
713
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport NotifyControlFramesWriteDone";
714
+ ping_manager_.NotifyPingSent(ping_timeout_);
677
715
  }
678
716
 
679
- auto Http2ClientTransport::OnWriteLoopEnded() {
680
- GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport OnWriteLoopEnded Factory";
681
- return
682
- [self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
683
- GRPC_HTTP2_CLIENT_DLOG
684
- << "Http2ClientTransport OnWriteLoopEnded Promise Status="
685
- << status;
686
- GRPC_UNUSED absl::Status error =
687
- self->HandleError(Http2Status::AbslConnectionError(
688
- status.code(), std::string(status.message())));
689
- };
717
+ auto Http2ClientTransport::SerializeAndWrite(std::vector<Http2Frame>&& frames) {
718
+ SliceBuffer output_buf;
719
+ should_reset_ping_clock_ =
720
+ Serialize(absl::Span<Http2Frame>(frames), output_buf)
721
+ .should_reset_ping_clock;
722
+ size_t output_buf_length = output_buf.Length();
723
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport SerializeAndWrite Write "
724
+ "output_buf.length() = "
725
+ << output_buf_length;
726
+ return AssertResultType<absl::Status>(If(
727
+ output_buf_length > 0,
728
+ [self = RefAsSubclass<Http2ClientTransport>(),
729
+ output_buf = std::move(output_buf)]() mutable {
730
+ return self->endpoint_.Write(std::move(output_buf),
731
+ PromiseEndpoint::WriteArgs{});
732
+ },
733
+ []() { return absl::OkStatus(); }));
690
734
  }
691
735
 
692
- auto Http2ClientTransport::StreamMultiplexerLoop() {
693
- GRPC_HTTP2_CLIENT_DLOG
694
- << "Http2ClientTransport StreamMultiplexerLoop Factory";
695
- // This loop iterates over all the writable streams and drains them. If
696
- // there are no writable streams, StreamMultiplexerLoop blocks until there
697
- // is a writable stream.
698
- return Loop([self = RefAsSubclass<Http2ClientTransport>()]() mutable {
699
- // Overview:
700
- // 1. Get the next writable stream.
701
- // 2. Dequeue frames from the stream queue based on available transport
702
- // tokens.
703
- // 3. If the stream is still writable, enqueue the stream back to the
704
- // writable stream list.
705
- // 4. Enqueue the dequeued frames to the MPSC queue.
706
- return TrySeq(
707
- self->writable_stream_list_.Next(/*transport_tokens_available*/ true),
708
- [self](const uint32_t stream_id) mutable
709
- -> absl::StatusOr<std::vector<Http2Frame>> {
710
- RefCountedPtr<Stream> stream = self->LookupStream(stream_id);
711
- if (GPR_UNLIKELY(stream == nullptr)) {
712
- // Stream was closed before we could dequeue.
713
- // TODO(akshitpatel) : [PH2][P2] : Race condition. Determine should
714
- // we have a DCHECK here based on how ResetStream/Aborts are
715
- // handled.
716
- return std::vector<Http2Frame>();
717
- }
736
+ absl::StatusOr<std::vector<Http2Frame>>
737
+ Http2ClientTransport::DequeueStreamFrames(RefCountedPtr<Stream> stream) {
738
+ // write_bytes_remaining_ is passed as an upper bound on the max
739
+ // number of tokens that can be dequeued to prevent dequeuing huge
740
+ // data frames when write_bytes_remaining_ is very low. As the
741
+ // available transport tokens can only range from 0 to 2^31 - 1,
742
+ // we are clamping the write_bytes_remaining_ to that range.
743
+ // TODO(akshitpatel) : [PH2][P3] : Plug transport_tokens when
744
+ // transport flow control is implemented.
745
+ StreamDataQueue<ClientMetadataHandle>::DequeueResult result =
746
+ stream->DequeueFrames(
747
+ /*transport_tokens*/ std::min(
748
+ std::numeric_limits<uint32_t>::max(),
749
+ static_cast<uint32_t>(Clamp<size_t>(write_bytes_remaining_, 0,
750
+ RFC9113::kMaxSize31Bit - 1))),
751
+ settings_.peer().max_frame_size(), encoder_);
752
+ if (result.is_writable) {
753
+ // Stream is still writable. Enqueue it back to the writable
754
+ // stream list.
755
+ // TODO(akshitpatel) : [PH2][P3] : Plug transport_tokens when
756
+ // transport flow control is implemented.
757
+ absl::Status status =
758
+ writable_stream_list_.Enqueue(stream, result.priority);
759
+ if (GPR_UNLIKELY(!status.ok())) {
760
+ GRPC_HTTP2_CLIENT_DLOG
761
+ << "Http2ClientTransport MultiplexerLoop Failed to "
762
+ "enqueue stream "
763
+ << stream->GetStreamId() << " with status: " << status;
764
+ // Close transport if we fail to enqueue stream.
765
+ return HandleError(std::nullopt, Http2Status::AbslConnectionError(
766
+ absl::StatusCode::kUnavailable,
767
+ std::string(status.message())));
768
+ }
769
+ }
770
+ if (result.InitialMetadataDequeued()) {
771
+ stream->SentInitialMetadata();
772
+ }
773
+ if (result.HalfCloseDequeued()) {
774
+ CloseStream(stream, CloseStreamArgs{/*close_reads=*/false,
775
+ /*close_writes=*/true});
776
+ stream->MarkHalfClosedLocal();
777
+ }
778
+ if (result.ResetStreamDequeued()) {
779
+ CloseStream(stream, CloseStreamArgs{/*close_reads=*/true,
780
+ /*close_writes=*/true});
781
+ stream->MarkHalfClosedLocal();
782
+ }
718
783
 
719
- // TODO(akshitpatel) : [PH2][P3] : Plug transport_tokens when
720
- // transport flow control is implemented.
721
- absl::StatusOr<StreamDataQueue<ClientMetadataHandle>::DequeueResult>
722
- result = stream->DequeueFrames(
723
- /*transport_tokens*/ std::numeric_limits<uint32_t>::max(),
724
- self->settings_.peer().max_frame_size(), self->encoder_);
725
- if (result.ok() && result->is_writable) {
726
- // Stream is still writable. Enqueue it back to the writable stream
727
- // list.
784
+ // Update the write_bytes_remaining_ based on the bytes consumed
785
+ // in the current dequeue.
786
+ write_bytes_remaining_ =
787
+ (write_bytes_remaining_ >= result.total_bytes_consumed)
788
+ ? (write_bytes_remaining_ - result.total_bytes_consumed)
789
+ : 0;
790
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport MultiplexerLoop "
791
+ "write_bytes_remaining_ after dequeue = "
792
+ << write_bytes_remaining_ << " total_bytes_consumed = "
793
+ << result.total_bytes_consumed
794
+ << " stream_id = " << stream->GetStreamId()
795
+ << " is_writable = " << result.is_writable
796
+ << " stream_priority = "
797
+ << static_cast<uint8_t>(result.priority)
798
+ << " number of frames = " << result.frames.size();
799
+ return std::move(result.frames);
800
+ }
801
+
802
+ auto Http2ClientTransport::MultiplexerLoop() {
803
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport MultiplexerLoop Factory";
804
+ return AssertResultType<
805
+ absl::Status>(Loop([self = RefAsSubclass<Http2ClientTransport>()]() {
806
+ self->write_bytes_remaining_ = self->GetMaxWriteSize();
807
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport MultiplexerLoop "
808
+ << " max_write_size_=" << self->GetMaxWriteSize();
809
+ return TrySeq(
810
+ self->writable_stream_list_.WaitForReady(
811
+ self->AreTransportFlowControlTokensAvailable()),
812
+ [self]() {
813
+ // TODO(akshitpatel) : [PH2][P2] : Return an `important` tag from
814
+ // WriteControlFrames() to indicate if we should do a separate write
815
+ // for the queued control frames or send the queued frames with the
816
+ // data frames(if any).
817
+ return Map(self->WriteControlFrames(), [self](absl::Status status) {
818
+ if (GPR_UNLIKELY(!status.ok())) {
819
+ GRPC_HTTP2_CLIENT_DLOG
820
+ << "Http2ClientTransport MultiplexerLoop Failed to "
821
+ "write control frames with status: "
822
+ << status;
823
+ return status;
824
+ }
825
+ self->NotifyControlFramesWriteDone();
826
+ return absl::OkStatus();
827
+ });
828
+ },
829
+ [self]() -> absl::StatusOr<std::vector<Http2Frame>> {
830
+ std::vector<Http2Frame> frames;
831
+ // Drain all the writable streams till we have written
832
+ // max_write_size_ bytes of data or there is no more data to send. In
833
+ // some cases, we may write more than max_write_size_ bytes(like
834
+ // writing metadata).
835
+ while (self->write_bytes_remaining_ > 0) {
728
836
  // TODO(akshitpatel) : [PH2][P3] : Plug transport_tokens when
729
837
  // transport flow control is implemented.
730
- absl::Status status = self->writable_stream_list_.Enqueue(
731
- stream_id, WritableStreams::StreamPriority::kDefault);
838
+ std::optional<RefCountedPtr<Stream>> optional_stream =
839
+ self->writable_stream_list_.ImmediateNext(
840
+ self->AreTransportFlowControlTokensAvailable());
841
+ if (!optional_stream.has_value()) {
842
+ GRPC_HTTP2_CLIENT_DLOG
843
+ << "Http2ClientTransport MultiplexerLoop "
844
+ "No writable streams available, write_bytes_remaining_ = "
845
+ << self->write_bytes_remaining_;
846
+ break;
847
+ }
848
+ RefCountedPtr<Stream> stream = std::move(optional_stream.value());
849
+ GRPC_HTTP2_CLIENT_DLOG
850
+ << "Http2ClientTransport MultiplexerLoop "
851
+ "Next writable stream id = "
852
+ << stream->GetStreamId()
853
+ << " is_closed_for_writes = " << stream->IsClosedForWrites();
854
+
855
+ if (GPR_LIKELY(!stream->IsClosedForWrites())) {
856
+ auto stream_frames = self->DequeueStreamFrames(stream);
857
+ if (GPR_UNLIKELY(!stream_frames.ok())) {
858
+ GRPC_HTTP2_CLIENT_DLOG
859
+ << "Http2ClientTransport MultiplexerLoop "
860
+ "Failed to dequeue stream frames with status: "
861
+ << stream_frames.status();
862
+ return stream_frames.status();
863
+ }
732
864
 
733
- if (GPR_UNLIKELY(!status.ok())) {
734
- LOG(ERROR) << "Failed to enqueue stream " << stream_id
735
- << " with status: " << status;
736
- // Close transport if we fail to enqueue stream.
737
- return absl::InternalError("Failed to enqueue stream");
865
+ frames.reserve(frames.size() + stream_frames.value().size());
866
+ frames.insert(
867
+ frames.end(),
868
+ std::make_move_iterator(stream_frames.value().begin()),
869
+ std::make_move_iterator(stream_frames.value().end()));
738
870
  }
739
- } else if (GPR_UNLIKELY(!result.ok())) {
740
- // Close the corresponding stream if we fail to dequeue frames from
741
- // the stream queue.
742
- LOG(ERROR) << "Failed to dequeue frames for stream " << stream_id
743
- << " with status: " << result.status();
744
- absl::Status status =
745
- self->HandleError(Http2Status::AbslStreamError(
746
- absl::StatusCode::kInternal, "Failed to dequeue frames"));
747
- return std::vector<Http2Frame>();
748
871
  }
872
+
749
873
  GRPC_HTTP2_CLIENT_DLOG
750
- << "Http2ClientTransport StreamMultiplexerLoop. Dequeued "
751
- << result->frames.size()
752
- << " frames for "
753
- "stream: "
754
- << stream_id;
755
- return std::move(result->frames);
874
+ << "Http2ClientTransport MultiplexerLoop "
875
+ "write_bytes_remaining_ after draining all writable streams = "
876
+ << self->write_bytes_remaining_;
877
+
878
+ return std::move(frames);
756
879
  },
757
880
  [self](std::vector<Http2Frame> frames) {
758
- // Enqueue the frames to the MPSC queue.
759
- return Loop([self, frames = std::move(frames), idx = 0u]() mutable {
760
- return If(
761
- idx < frames.size(),
762
- [self, &frames, &idx]() {
763
- return Map(
764
- // Enqueue to the MPSC queue could return pending. This
765
- // induces backpressure for the sender. Only after writing
766
- // to the MPSC queue we will loop back to read more
767
- // streams.
768
- self->EnqueueOutgoingFrame(std::move(frames[idx++])),
769
- [](absl::Status status) -> LoopCtl<absl::Status> {
770
- if (GPR_UNLIKELY(!status.ok())) {
771
- return status;
772
- }
773
- return Continue{};
774
- });
775
- },
776
- []() -> LoopCtl<absl::Status> { return absl::OkStatus(); });
777
- });
881
+ return self->SerializeAndWrite(std::move(frames));
778
882
  },
779
- []() -> LoopCtl<absl::Status> { return Continue{}; });
780
- });
883
+ [self]() -> LoopCtl<absl::Status> {
884
+ if (self->should_reset_ping_clock_) {
885
+ GRPC_HTTP2_CLIENT_DLOG
886
+ << "Http2ClientTransport MultiplexerLoop ResetPingClock";
887
+ self->ping_manager_.ResetPingClock(/*is_client=*/true);
888
+ self->should_reset_ping_clock_ = false;
889
+ }
890
+ return Continue();
891
+ });
892
+ }));
781
893
  }
782
894
 
783
- auto Http2ClientTransport::OnStreamMultiplexerLoopEnded() {
895
+ auto Http2ClientTransport::OnMultiplexerLoopEnded() {
784
896
  GRPC_HTTP2_CLIENT_DLOG
785
- << "Http2ClientTransport OnStreamMultiplexerLoopEnded Factory";
786
- return [self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
787
- GRPC_HTTP2_CLIENT_DLOG
788
- << "Http2ClientTransport OnStreamMultiplexerLoopEnded Promise Status="
789
- << status;
790
- GRPC_UNUSED absl::Status error =
791
- self->HandleError(Http2Status::AbslConnectionError(
792
- status.code(), std::string(status.message())));
793
- };
897
+ << "Http2ClientTransport OnMultiplexerLoopEnded Factory";
898
+ return
899
+ [self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
900
+ GRPC_HTTP2_CLIENT_DLOG
901
+ << "Http2ClientTransport OnMultiplexerLoopEnded Promise Status="
902
+ << status;
903
+ GRPC_UNUSED absl::Status error = self->HandleError(
904
+ std::nullopt, Http2Status::AbslConnectionError(
905
+ status.code(), std::string(status.message())));
906
+ };
794
907
  }
795
908
 
796
909
  ///////////////////////////////////////////////////////////////////////////////
@@ -800,10 +913,11 @@ Http2ClientTransport::Http2ClientTransport(
800
913
  PromiseEndpoint endpoint, GRPC_UNUSED const ChannelArgs& channel_args,
801
914
  std::shared_ptr<EventEngine> event_engine,
802
915
  grpc_closure* on_receive_settings)
803
- : endpoint_(std::move(endpoint)),
804
- outgoing_frames_(kMpscSize),
916
+ : channelz::DataSource(http2::CreateChannelzSocketNode(
917
+ endpoint.GetEventEngineEndpoint(), channel_args)),
918
+ endpoint_(std::move(endpoint)),
805
919
  stream_id_mutex_(/*Initial Stream Id*/ 1),
806
- bytes_sent_in_last_write_(false),
920
+ should_reset_ping_clock_(false),
807
921
  incoming_header_in_progress_(false),
808
922
  incoming_header_end_stream_(false),
809
923
  is_first_write_(true),
@@ -811,6 +925,7 @@ Http2ClientTransport::Http2ClientTransport(
811
925
  on_receive_settings_(on_receive_settings),
812
926
  max_header_list_size_soft_limit_(
813
927
  GetSoftLimitFromChannelArgs(channel_args)),
928
+ max_write_size_(kMaxWriteSize),
814
929
  keepalive_time_(std::max(
815
930
  Duration::Seconds(10),
816
931
  channel_args.GetDurationFromIntMillis(GRPC_ARG_KEEPALIVE_TIME_MS)
@@ -838,24 +953,38 @@ Http2ClientTransport::Http2ClientTransport(
838
953
  ((keepalive_timeout_ < ping_timeout_) ? keepalive_timeout_
839
954
  : Duration::Infinity()),
840
955
  keepalive_time_),
841
- keepalive_permit_without_calls_(false) {
956
+ keepalive_permit_without_calls_(
957
+ channel_args.GetBool(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)
958
+ .value_or(false)),
959
+ enable_preferred_rx_crypto_frame_advertisement_(
960
+ channel_args
961
+ .GetBool(GRPC_ARG_EXPERIMENTAL_HTTP2_PREFERRED_CRYPTO_FRAME_SIZE)
962
+ .value_or(false)),
963
+ memory_owner_(channel_args.GetObject<ResourceQuota>()
964
+ ->memory_quota()
965
+ ->CreateMemoryOwner()),
966
+ flow_control_(
967
+ "PH2_Client",
968
+ channel_args.GetBool(GRPC_ARG_HTTP2_BDP_PROBE).value_or(true),
969
+ &memory_owner_),
970
+ ztrace_collector_(std::make_shared<PromiseHttp2ZTraceCollector>()) {
842
971
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Constructor Begin";
972
+ SourceConstructed();
843
973
 
844
974
  InitLocalSettings(settings_.mutable_local(), /*is_client=*/true);
845
975
  ReadSettingsFromChannelArgs(channel_args, settings_.mutable_local(),
846
- /*is_client=*/true);
976
+ flow_control_, /*is_client=*/true);
847
977
 
848
978
  // Initialize the general party and write party.
849
979
  auto general_party_arena = SimpleArenaAllocator(0)->MakeArena();
850
980
  general_party_arena->SetContext<EventEngine>(event_engine.get());
851
981
  general_party_ = Party::Make(std::move(general_party_arena));
852
982
 
853
- general_party_->Spawn("ReadLoop", ReadLoop(), OnReadLoopEnded());
854
- // TODO(tjagtap) : [PH2][P2] Fix when needed.
855
- general_party_->Spawn("WriteLoop", WriteLoop(), OnWriteLoopEnded());
856
- general_party_->Spawn("StreamMultiplexerLoop", StreamMultiplexerLoop(),
857
- OnStreamMultiplexerLoopEnded());
858
-
983
+ general_party_->Spawn("ReadLoop", UntilTransportClosed(ReadLoop()),
984
+ OnReadLoopEnded());
985
+ general_party_->Spawn("MultiplexerLoop",
986
+ UntilTransportClosed(MultiplexerLoop()),
987
+ OnMultiplexerLoopEnded());
859
988
  // The keepalive loop is only spawned if the keepalive time is not infinity.
860
989
  keepalive_manager_.Spawn(general_party_.get());
861
990
 
@@ -867,7 +996,7 @@ Http2ClientTransport::Http2ClientTransport(
867
996
  Http2ErrorCode code = settings_.mutable_local().Apply(
868
997
  Http2Settings::kInitialWindowSizeWireId,
869
998
  (Http2Settings::max_initial_window_size() - 1));
870
- DCHECK(code == Http2ErrorCode::kNoError);
999
+ GRPC_DCHECK(code == Http2ErrorCode::kNoError);
871
1000
  // </DeleteAfterFlowControl>
872
1001
 
873
1002
  const int max_hpack_table_size =
@@ -876,79 +1005,127 @@ Http2ClientTransport::Http2ClientTransport(
876
1005
  encoder_.SetMaxUsableSize(max_hpack_table_size);
877
1006
  }
878
1007
 
879
- settings_timeout_ =
880
- channel_args.GetDurationFromIntMillis(GRPC_ARG_SETTINGS_TIMEOUT)
881
- .value_or(std::max(keepalive_timeout_ * 2, Duration::Minutes(1)));
1008
+ transport_settings_.SetSettingsTimeout(channel_args, keepalive_timeout_);
882
1009
 
883
- std::optional<Http2SettingsFrame> settings_frame =
884
- settings_.MaybeSendUpdate();
885
- if (settings_frame.has_value()) {
886
- GRPC_HTTP2_CLIENT_DLOG
887
- << "Http2ClientTransport Constructor Spawn SendFirstSettingsFrame";
888
- general_party_->Spawn(
889
- "SendFirstSettingsFrame",
890
- [self = RefAsSubclass<Http2ClientTransport>(),
891
- frame = std::move(*settings_frame)]() mutable {
892
- return self->EnqueueOutgoingFrame(std::move(frame));
893
- },
894
- [](GRPC_UNUSED absl::Status status) {});
895
- }
896
1010
  if (settings_.local().allow_security_frame()) {
897
1011
  // TODO(tjagtap) : [PH2][P3] : Setup the plumbing to pass the security frame
898
1012
  // to the endpoing via TransportFramingEndpointExtension.
899
1013
  // Also decide if this plumbing is done here, or when the peer sends
900
1014
  // allow_security_frame too.
901
1015
  }
1016
+
1017
+ // Spawn a promise to flush the gRPC initial connection string and settings
1018
+ // frames.
1019
+ general_party_->Spawn("SpawnFlushInitialFrames", TriggerWriteCycle(),
1020
+ [](GRPC_UNUSED absl::Status status) {});
1021
+
902
1022
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Constructor End";
903
1023
  }
904
1024
 
905
- // This function MUST be idempotent.
906
- void Http2ClientTransport::CloseStream(uint32_t stream_id, absl::Status status,
1025
+ // This function MUST be idempotent. This function MUST be called from the
1026
+ // transport party.
1027
+ void Http2ClientTransport::CloseStream(RefCountedPtr<Stream> stream,
907
1028
  CloseStreamArgs args,
908
1029
  DebugLocation whence) {
1030
+ // TODO(akshitpatel) : [PH2][P3] : Measure the impact of holding mutex
1031
+ // throughout this function.
1032
+ MutexLock lock(&transport_mutex_);
1033
+ GRPC_DCHECK(stream != nullptr) << "stream is null";
909
1034
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::CloseStream for stream id: "
910
- << stream_id << " status=" << status
1035
+ << stream->GetStreamId()
911
1036
  << " location=" << whence.file() << ":"
912
1037
  << whence.line();
913
1038
 
914
- // TODO(akshitpatel) : [PH2][P3] : Measure the impact of holding mutex
915
- // throughout this function.
916
- MutexLock lock(&transport_mutex_);
917
- auto pair = stream_list_.find(stream_id);
918
- if (pair == stream_list_.end()) {
919
- GRPC_HTTP2_CLIENT_DLOG
920
- << "Http2ClientTransport::CloseStream for stream id: " << stream_id
921
- << " stream not found";
922
- return;
1039
+ if (args.close_writes) {
1040
+ stream->SetWriteClosed();
923
1041
  }
924
- auto& stream = pair->second;
925
1042
 
926
1043
  if (args.close_reads) {
927
- stream->MarkHalfClosedRemote();
928
- }
929
- if (args.close_writes) {
930
- stream->MarkHalfClosedLocal();
1044
+ GRPC_HTTP2_CLIENT_DLOG
1045
+ << "Http2ClientTransport::CloseStream for stream id: "
1046
+ << stream->GetStreamId() << " closing stream for reads.";
1047
+ stream_list_.erase(stream->GetStreamId());
931
1048
  }
1049
+ }
932
1050
 
933
- if (stream->IsClosed()) {
934
- GRPC_HTTP2_CLIENT_DLOG
935
- << "Http2ClientTransport::CloseStream for stream id: " << stream_id
936
- << " closing stream.";
937
- if (args.send_rst_stream) {
938
- // TODO(akshitpatel) : [PH2][P2] : Send RST_STREAM frame.
1051
+ // Here is the flow for stream close:
1052
+ // 1. BeginCloseStream is invoked if the transport needs to close the stream.
1053
+ // 2. If reset stream does not need to be sent, the stream is closed for reads
1054
+ // and writes immediately. Also, the stream is removed from the
1055
+ // stream_list_.
1056
+ // 3. If reset stream needs to be sent and the stream is cancelled, the stream
1057
+ // is closed for reads immediately. This will result in stream being removed
1058
+ // from the stream_list_. Additionally, the reset stream frame is enqueued
1059
+ // and the stream is closed for writes once the frame is created.
1060
+ // 4. Trailing metadata is pushed to the call stack.
1061
+ // Extended:
1062
+ // 5. Eventually CallHandler.OnDone() is invoked.
1063
+ // 6. If the call was cancelled, we try to enqueue a reset stream frame. In most
1064
+ // of the cases, this would be a no-op. The only case where this would
1065
+ // enqueue the reset stream frame is an application initiated abort.
1066
+ // 7. If the call was not cancelled, we try to enqueue a half close frame. If
1067
+ // the stream was already closed from writes, this would be a no-op.
1068
+ void Http2ClientTransport::BeginCloseStream(
1069
+ const uint32_t stream_id, std::optional<uint32_t> reset_stream_error_code,
1070
+ ServerMetadataHandle&& metadata, DebugLocation whence) {
1071
+ GRPC_HTTP2_CLIENT_DLOG
1072
+ << "Http2ClientTransport::BeginCloseStream for stream id: " << stream_id
1073
+ << " error_code="
1074
+ << (reset_stream_error_code.has_value()
1075
+ ? absl::StrCat(*reset_stream_error_code)
1076
+ : "nullopt")
1077
+ << " ServerMetadata=" << metadata->DebugString()
1078
+ << " location=" << whence.file() << ":" << whence.line();
1079
+
1080
+ RefCountedPtr<Stream> stream = LookupStream(stream_id);
1081
+ if (stream != nullptr) {
1082
+ if (stream->did_push_trailing_metadata) {
1083
+ return;
939
1084
  }
940
1085
 
941
- if (args.push_trailing_metadata) {
942
- stream->call.SpawnPushServerTrailingMetadata(
943
- ServerMetadataFromStatus(status));
1086
+ // If reset stream needs to be sent, CloseStream will be called from the
1087
+ // Multiplexer after the reset stream frame is created.
1088
+ if (!reset_stream_error_code) {
1089
+ // Callers taking this path:
1090
+ // 1. Reading a RST stream frame (will not send any frame out).
1091
+
1092
+ CloseStream(stream,
1093
+ CloseStreamArgs{/*close_reads*/ true, /*close_writes=*/true},
1094
+ whence);
1095
+ stream->MarkHalfClosedRemote();
1096
+ } else {
1097
+ // Callers taking this path:
1098
+ // 1. Reading Trailing Metadata (MAY send half close from OnDone).
1099
+ // 2. Processing Error in transport (will send reset stream from here).
1100
+
1101
+ if (metadata->get(GrpcCallWasCancelled())) {
1102
+ CloseStream(
1103
+ stream,
1104
+ CloseStreamArgs{/*close_reads*/ true, /*close_writes=*/false},
1105
+ whence);
1106
+ absl::StatusOr<EnqueueResult> enqueue_result =
1107
+ stream->EnqueueResetStream(reset_stream_error_code.value());
1108
+ GRPC_HTTP2_CLIENT_DLOG << "Enqueued ResetStream with error code="
1109
+ << reset_stream_error_code.value()
1110
+ << " status=" << enqueue_result.status();
1111
+ if (enqueue_result.ok()) {
1112
+ GRPC_UNUSED absl::Status status = MaybeAddStreamToWritableStreamList(
1113
+ stream, enqueue_result.value());
1114
+ }
1115
+ }
944
1116
  }
945
- stream_list_.erase(stream_id);
1117
+
1118
+ stream->did_push_trailing_metadata = true;
1119
+ // This maybe called multiple times while closing a stream. This should be
1120
+ // fine as the the call spine ignores the subsequent calls.
1121
+ stream->call.SpawnPushServerTrailingMetadata(std::move(metadata));
946
1122
  }
947
1123
  }
948
1124
 
949
1125
  void Http2ClientTransport::CloseTransport() {
950
1126
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::CloseTransport";
951
1127
 
1128
+ transport_closed_latch_.Set();
952
1129
  // This is the only place where the general_party_ is
953
1130
  // reset.
954
1131
  general_party_.reset();
@@ -995,8 +1172,11 @@ void Http2ClientTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
995
1172
  // fail. Also, as this is running on the transport
996
1173
  // party, there would not be concurrent access to the stream.
997
1174
  auto& stream = pair.second;
998
- stream->call.SpawnPushServerTrailingMetadata(
999
- ServerMetadataFromStatus(http2_status.GetAbslConnectionError()));
1175
+ self->BeginCloseStream(stream->stream_id,
1176
+ Http2ErrorCodeToRstFrameErrorCode(
1177
+ http2_status.GetConnectionErrorCode()),
1178
+ CancelledServerMetadataFromStatus(
1179
+ http2_status.GetAbslConnectionError()));
1000
1180
  }
1001
1181
 
1002
1182
  // RFC9113 : A GOAWAY frame might not immediately precede closing of
@@ -1017,15 +1197,30 @@ void Http2ClientTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1017
1197
 
1018
1198
  Http2ClientTransport::~Http2ClientTransport() {
1019
1199
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Destructor Begin";
1020
- DCHECK(stream_list_.empty());
1200
+ GRPC_DCHECK(stream_list_.empty());
1201
+ memory_owner_.Reset();
1202
+ SourceDestructing();
1021
1203
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Destructor End";
1022
1204
  }
1023
1205
 
1206
+ void Http2ClientTransport::AddData(channelz::DataSink sink) {
1207
+ sink.AddData(
1208
+ "Http2ClientTransport",
1209
+ channelz::PropertyList()
1210
+ .Set("settings", settings_.ChannelzProperties())
1211
+ .Set("keepalive_time", keepalive_time_)
1212
+ .Set("keepalive_timeout", keepalive_timeout_)
1213
+ .Set("ping_timeout", ping_timeout_)
1214
+ .Set("keepalive_permit_without_calls",
1215
+ keepalive_permit_without_calls_)
1216
+ .Set("flow_control", flow_control_.stats().ChannelzProperties()));
1217
+ general_party_->ExportToChannelz("Http2ClientTransport Party", sink);
1218
+ }
1219
+
1024
1220
  ///////////////////////////////////////////////////////////////////////////////
1025
1221
  // Stream Related Operations
1026
1222
 
1027
- RefCountedPtr<Http2ClientTransport::Stream> Http2ClientTransport::LookupStream(
1028
- uint32_t stream_id) {
1223
+ RefCountedPtr<Stream> Http2ClientTransport::LookupStream(uint32_t stream_id) {
1029
1224
  MutexLock lock(&transport_mutex_);
1030
1225
  auto it = stream_list_.find(stream_id);
1031
1226
  if (it == stream_list_.end()) {
@@ -1037,8 +1232,45 @@ RefCountedPtr<Http2ClientTransport::Stream> Http2ClientTransport::LookupStream(
1037
1232
  return it->second;
1038
1233
  }
1039
1234
 
1040
- bool Http2ClientTransport::MakeStream(CallHandler call_handler,
1041
- const uint32_t stream_id) {
1235
+ bool Http2ClientTransport::SetOnDone(CallHandler call_handler,
1236
+ RefCountedPtr<Stream> stream) {
1237
+ return call_handler.OnDone(
1238
+ [self = RefAsSubclass<Http2ClientTransport>(), stream,
1239
+ stream_id = stream->GetStreamId()](bool cancelled) {
1240
+ GRPC_HTTP2_CLIENT_DLOG << "PH2: Client call " << self.get()
1241
+ << " id=" << stream_id
1242
+ << " done: cancelled=" << cancelled;
1243
+ absl::StatusOr<EnqueueResult> enqueue_result;
1244
+ GRPC_HTTP2_CLIENT_DLOG
1245
+ << "PH2: Client call " << self.get() << " id=" << stream_id
1246
+ << " done: stream=" << stream.get() << " cancelled=" << cancelled;
1247
+ if (cancelled) {
1248
+ // In most of the cases, EnqueueResetStream would be a no-op as
1249
+ // BeginCloseStream would have already enqueued the reset stream.
1250
+ // Currently only Aborts from application will actually enqueue
1251
+ // the reset stream here.
1252
+ enqueue_result = stream->EnqueueResetStream(
1253
+ static_cast<uint32_t>(Http2ErrorCode::kCancel));
1254
+ GRPC_HTTP2_CLIENT_DLOG
1255
+ << "Enqueued ResetStream with error code="
1256
+ << static_cast<uint32_t>(Http2ErrorCode::kCancel)
1257
+ << " status=" << enqueue_result.status();
1258
+ } else {
1259
+ enqueue_result = stream->EnqueueHalfClosed();
1260
+ GRPC_HTTP2_CLIENT_DLOG << "Enqueued HalfClosed with result="
1261
+ << enqueue_result.status();
1262
+ }
1263
+
1264
+ if (enqueue_result.ok()) {
1265
+ GRPC_UNUSED absl::Status status =
1266
+ self->MaybeAddStreamToWritableStreamList(stream,
1267
+ enqueue_result.value());
1268
+ }
1269
+ });
1270
+ }
1271
+
1272
+ std::optional<RefCountedPtr<Stream>> Http2ClientTransport::MakeStream(
1273
+ CallHandler call_handler, const uint32_t stream_id) {
1042
1274
  // https://datatracker.ietf.org/doc/html/rfc9113#name-stream-identifiers
1043
1275
  // TODO(tjagtap) : [PH2][P2] Validate implementation.
1044
1276
 
@@ -1047,118 +1279,62 @@ bool Http2ClientTransport::MakeStream(CallHandler call_handler,
1047
1279
  // OnDone needs to be synchronous and hence InterActivityMutex might not be
1048
1280
  // an option to protect the stream_list_.
1049
1281
  MutexLock lock(&transport_mutex_);
1050
- const bool on_done_added =
1051
- call_handler.OnDone([self = RefAsSubclass<Http2ClientTransport>(),
1052
- stream_id](bool cancelled) {
1053
- GRPC_HTTP2_CLIENT_DLOG << "PH2: Client call " << self.get()
1054
- << " id=" << stream_id
1055
- << " done: cancelled=" << cancelled;
1056
- if (cancelled) {
1057
- // TODO(akshitpatel) : [PH2][P2] : There are two ways to handle
1058
- // cancellation.
1059
- // 1. Call CloseStream from the on_done callback as done here. This
1060
- // will be invoked when PullServerTrailingMetadata resolves.
1061
- // 2. Call CloseStream from the OutboundLoop. When the call is
1062
- // cancelled, for_each() should return with an error. The
1063
- // WasCancelled() function can be used to determinie if the call
1064
- // was cancelled.
1065
- // At this point, both the above mentioned approaches seem to be more
1066
- // or less the same as both are running on the call party.
1067
- self->CloseStream(stream_id, absl::CancelledError(),
1068
- CloseStreamArgs{
1069
- /*close_reads=*/true,
1070
- /*close_writes=*/true,
1071
- /*send_rst_stream=*/true,
1072
- /*push_trailing_metadata=*/false,
1073
- });
1074
- }
1075
- });
1076
- if (!on_done_added) return false;
1077
- stream_list_.emplace(
1078
- stream_id, MakeRefCounted<Stream>(std::move(call_handler), stream_id));
1079
- return true;
1282
+ RefCountedPtr<Stream> stream = MakeRefCounted<Stream>(
1283
+ call_handler, stream_id, settings_.peer().allow_true_binary_metadata(),
1284
+ settings_.acked().allow_true_binary_metadata(), flow_control_);
1285
+ const bool on_done_added = SetOnDone(call_handler, stream);
1286
+ if (!on_done_added) return std::nullopt;
1287
+ stream_list_.emplace(stream_id, stream);
1288
+ return stream;
1080
1289
  }
1081
1290
 
1082
1291
  ///////////////////////////////////////////////////////////////////////////////
1083
1292
  // Call Spine related operations
1084
1293
 
1085
1294
  auto Http2ClientTransport::CallOutboundLoop(
1086
- CallHandler call_handler, const uint32_t stream_id,
1295
+ CallHandler call_handler, RefCountedPtr<Stream> stream,
1087
1296
  InterActivityMutex<uint32_t>::Lock lock /* Locked stream_id_mutex */,
1088
1297
  ClientMetadataHandle metadata) {
1089
1298
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport CallOutboundLoop";
1299
+ GRPC_DCHECK(stream != nullptr);
1090
1300
 
1091
1301
  auto send_message = [self = RefAsSubclass<Http2ClientTransport>(),
1092
- stream_id](MessageHandle&& message) mutable {
1093
- RefCountedPtr<Stream> stream = self->LookupStream(stream_id);
1094
- return If(
1095
- stream != nullptr,
1096
- [self, stream, message = std::move(message), stream_id]() mutable {
1097
- return TrySeq(stream->EnqueueMessage(std::move(message)),
1098
- [self, stream_id](bool became_writable) {
1099
- GRPC_HTTP2_CLIENT_DLOG
1100
- << "Http2ClientTransport CallOutboundLoop "
1101
- "Enqueued Message";
1102
- return self->MaybeAddStreamToWritableStreamList(
1103
- stream_id, became_writable);
1104
- });
1105
- },
1106
- []() {
1107
- // This will trigger Call stack cleanup.
1108
- return absl::InternalError("Stream not found while sending message");
1109
- });
1302
+ stream](MessageHandle&& message) mutable {
1303
+ return TrySeq(stream->EnqueueMessage(std::move(message)),
1304
+ [self, stream](const EnqueueResult result) mutable {
1305
+ GRPC_HTTP2_CLIENT_DLOG
1306
+ << "Http2ClientTransport CallOutboundLoop "
1307
+ "Enqueued Message";
1308
+ return self->MaybeAddStreamToWritableStreamList(
1309
+ std::move(stream), result);
1310
+ });
1110
1311
  };
1111
1312
 
1112
1313
  auto send_initial_metadata = [self = RefAsSubclass<Http2ClientTransport>(),
1113
- stream_id,
1314
+ stream,
1114
1315
  metadata = std::move(metadata)]() mutable {
1115
- RefCountedPtr<Stream> stream = self->LookupStream(stream_id);
1116
- return If(
1117
- stream != nullptr,
1118
- [self, stream, metadata = std::move(metadata), stream_id]() mutable {
1119
- return TrySeq(
1120
- stream->EnqueueInitialMetadata(std::move(metadata)),
1121
- [self, stream_id](bool became_writable) {
1122
- GRPC_HTTP2_CLIENT_DLOG
1123
- << "Http2ClientTransport CallOutboundLoop "
1124
- "Enqueued Initial Metadata";
1125
- return self->MaybeAddStreamToWritableStreamList(
1126
- stream_id, became_writable);
1127
- },
1128
- [stream] {
1129
- // TODO(akshitpatel) : [PH2][P2] : Think how to handle stream
1130
- // states.
1131
- stream->SentInitialMetadata();
1132
- return absl::OkStatus();
1133
- });
1316
+ return TrySeq(
1317
+ [stream, metadata = std::move(metadata)]() mutable {
1318
+ return stream->EnqueueInitialMetadata(std::move(metadata));
1134
1319
  },
1135
- []() {
1136
- // This will trigger Call stack cleanup.
1137
- return absl::InternalError(
1138
- "Stream not found while sending initial metadata");
1320
+ [self, stream](const EnqueueResult result) mutable {
1321
+ GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport CallOutboundLoop "
1322
+ "Enqueued Initial Metadata";
1323
+ return self->MaybeAddStreamToWritableStreamList(std::move(stream),
1324
+ result);
1139
1325
  });
1140
1326
  };
1141
1327
 
1142
1328
  auto send_half_closed = [self = RefAsSubclass<Http2ClientTransport>(),
1143
- stream_id]() mutable {
1144
- RefCountedPtr<Stream> stream = self->LookupStream(stream_id);
1145
- return If(
1146
- stream != nullptr,
1147
- [self, stream, stream_id]() mutable {
1148
- return TrySeq(stream->EnqueueHalfClosed(),
1149
- [self, stream_id](bool became_writable) {
1150
- GRPC_HTTP2_CLIENT_DLOG
1151
- << "Http2ClientTransport CallOutboundLoop "
1152
- "Enqueued Half Closed";
1153
- return self->MaybeAddStreamToWritableStreamList(
1154
- stream_id, became_writable);
1155
- });
1156
- },
1157
- []() {
1158
- // This will trigger Call stack cleanup.
1159
- return absl::InternalError(
1160
- "Stream not found while sending half closed");
1161
- });
1329
+ stream]() mutable {
1330
+ return TrySeq([stream]() { return stream->EnqueueHalfClosed(); },
1331
+ [self, stream](const EnqueueResult result) mutable {
1332
+ GRPC_HTTP2_CLIENT_DLOG
1333
+ << "Http2ClientTransport CallOutboundLoop "
1334
+ "Enqueued Half Closed";
1335
+ return self->MaybeAddStreamToWritableStreamList(
1336
+ std::move(stream), result);
1337
+ });
1162
1338
  };
1163
1339
  return GRPC_LATENT_SEE_PROMISE(
1164
1340
  "Ph2CallOutboundLoop",
@@ -1214,12 +1390,13 @@ void Http2ClientTransport::StartCall(CallHandler call_handler) {
1214
1390
  // from a client than is allowed by the clients settings, whether or
1215
1391
  // not we should fail is debatable.
1216
1392
  const uint32_t stream_id = self->NextStreamId(std::get<0>(args));
1393
+ std::optional<RefCountedPtr<Stream>> stream =
1394
+ self->MakeStream(call_handler, stream_id);
1217
1395
  return If(
1218
- self->MakeStream(call_handler, stream_id),
1219
- [self, call_handler, stream_id,
1220
- args = std::move(args)]() mutable {
1396
+ stream.has_value(),
1397
+ [self, call_handler, stream, args = std::move(args)]() mutable {
1221
1398
  return Map(
1222
- self->CallOutboundLoop(call_handler, stream_id,
1399
+ self->CallOutboundLoop(call_handler, stream.value(),
1223
1400
  std::move(std::get<0>(args)),
1224
1401
  std::move(std::get<1>(args))),
1225
1402
  [](absl::Status status) { return status; });