grpc 1.0.1 → 1.1.2

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 (705) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +3696 -867
  3. data/etc/roots.pem +39 -111
  4. data/include/grpc/byte_buffer.h +64 -1
  5. data/include/grpc/census.h +40 -96
  6. data/include/grpc/compression.h +2 -1
  7. data/include/grpc/grpc.h +42 -7
  8. data/include/grpc/grpc_posix.h +8 -5
  9. data/include/grpc/impl/codegen/atm.h +3 -0
  10. data/include/grpc/impl/codegen/atm_gcc_atomic.h +2 -0
  11. data/include/grpc/impl/codegen/atm_gcc_sync.h +8 -0
  12. data/include/grpc/impl/codegen/atm_windows.h +4 -0
  13. data/include/grpc/impl/codegen/byte_buffer_reader.h +4 -4
  14. data/include/grpc/impl/codegen/compression_types.h +1 -1
  15. data/include/grpc/impl/codegen/connectivity_state.h +2 -0
  16. data/include/grpc/impl/codegen/exec_ctx_fwd.h +41 -0
  17. data/include/grpc/impl/codegen/gpr_slice.h +84 -0
  18. data/include/grpc/impl/codegen/{alloc.h → gpr_types.h} +30 -29
  19. data/include/grpc/impl/codegen/grpc_types.h +91 -9
  20. data/include/grpc/impl/codegen/port_platform.h +25 -92
  21. data/include/grpc/impl/codegen/slice.h +54 -97
  22. data/include/grpc/impl/codegen/sync.h +0 -253
  23. data/include/grpc/module.modulemap +0 -2
  24. data/include/grpc/slice.h +132 -0
  25. data/include/grpc/{impl/codegen/slice_buffer.h → slice_buffer.h} +22 -39
  26. data/include/grpc/support/alloc.h +40 -1
  27. data/include/grpc/support/log.h +80 -1
  28. data/include/grpc/support/log_windows.h +2 -0
  29. data/include/grpc/support/string_util.h +1 -1
  30. data/include/grpc/support/sync.h +252 -0
  31. data/include/grpc/support/time.h +67 -1
  32. data/src/boringssl/err_data.c +639 -627
  33. data/src/core/ext/census/base_resources.c +71 -0
  34. data/src/core/ext/census/base_resources.h +39 -0
  35. data/src/core/ext/census/gen/census.pb.c +26 -29
  36. data/src/core/ext/census/gen/census.pb.h +68 -67
  37. data/src/core/ext/census/gen/trace_context.pb.c +81 -0
  38. data/src/core/ext/census/gen/trace_context.pb.h +99 -0
  39. data/src/core/ext/census/grpc_filter.c +22 -16
  40. data/src/core/ext/census/grpc_plugin.c +2 -1
  41. data/src/core/ext/census/initialize.c +16 -4
  42. data/src/core/ext/census/mlog.h +1 -1
  43. data/src/core/ext/census/placeholders.c +0 -45
  44. data/src/core/ext/census/resource.c +312 -0
  45. data/src/core/ext/census/resource.h +63 -0
  46. data/src/core/ext/census/trace_context.c +86 -0
  47. data/src/core/ext/census/trace_context.h +68 -0
  48. data/src/core/ext/census/tracing.c +8 -2
  49. data/src/core/ext/{client_config → client_channel}/channel_connectivity.c +8 -4
  50. data/src/core/ext/client_channel/client_channel.c +1218 -0
  51. data/src/core/ext/{client_config → client_channel}/client_channel.h +8 -11
  52. data/src/core/ext/{client_config → client_channel}/client_channel_factory.c +33 -3
  53. data/src/core/ext/{client_config → client_channel}/client_channel_factory.h +15 -8
  54. data/src/core/ext/{client_config/client_config_plugin.c → client_channel/client_channel_plugin.c} +16 -15
  55. data/src/core/ext/{client_config → client_channel}/connector.c +1 -1
  56. data/src/core/ext/{client_config → client_channel}/connector.h +5 -8
  57. data/{include/grpc/support/slice_buffer.h → src/core/ext/client_channel/default_initial_connect_string.c} +4 -5
  58. data/src/core/ext/client_channel/http_connect_handshaker.c +399 -0
  59. data/src/core/ext/client_channel/http_connect_handshaker.h +52 -0
  60. data/src/core/ext/{client_config → client_channel}/initial_connect_string.c +6 -7
  61. data/src/core/ext/{client_config → client_channel}/initial_connect_string.h +10 -10
  62. data/src/core/ext/{client_config → client_channel}/lb_policy.c +11 -11
  63. data/src/core/ext/{client_config → client_channel}/lb_policy.h +68 -27
  64. data/src/core/ext/client_channel/lb_policy_factory.c +163 -0
  65. data/src/core/ext/{client_config → client_channel}/lb_policy_factory.h +64 -9
  66. data/src/core/ext/{client_config → client_channel}/lb_policy_registry.c +6 -4
  67. data/src/core/ext/{client_config → client_channel}/lb_policy_registry.h +4 -4
  68. data/src/core/ext/{client_config → client_channel}/parse_address.c +21 -14
  69. data/src/core/ext/{client_config → client_channel}/parse_address.h +8 -10
  70. data/src/core/ext/{client_config → client_channel}/resolver.c +3 -4
  71. data/src/core/ext/{client_config → client_channel}/resolver.h +11 -15
  72. data/src/core/ext/{client_config → client_channel}/resolver_factory.c +4 -3
  73. data/src/core/ext/{client_config → client_channel}/resolver_factory.h +13 -11
  74. data/src/core/ext/{client_config → client_channel}/resolver_registry.c +54 -34
  75. data/src/core/ext/{client_config → client_channel}/resolver_registry.h +21 -8
  76. data/src/core/ext/{client_config → client_channel}/subchannel.c +208 -119
  77. data/src/core/ext/{client_config → client_channel}/subchannel.h +21 -11
  78. data/src/core/ext/{client_config → client_channel}/subchannel_index.c +6 -17
  79. data/src/core/ext/{client_config → client_channel}/subchannel_index.h +7 -7
  80. data/src/core/ext/{client_config → client_channel}/uri_parser.c +21 -28
  81. data/src/core/ext/{client_config → client_channel}/uri_parser.h +3 -3
  82. data/src/core/ext/lb_policy/grpclb/grpclb.c +1406 -0
  83. data/src/core/ext/lb_policy/grpclb/grpclb.h +44 -0
  84. data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +117 -37
  85. data/src/core/ext/lb_policy/grpclb/load_balancer_api.h +31 -12
  86. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +6 -36
  87. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +22 -42
  88. data/src/core/ext/lb_policy/pick_first/pick_first.c +64 -46
  89. data/src/core/ext/lb_policy/round_robin/round_robin.c +324 -160
  90. data/src/core/ext/load_reporting/load_reporting.c +7 -56
  91. data/src/core/ext/load_reporting/load_reporting.h +41 -28
  92. data/src/core/ext/load_reporting/load_reporting_filter.c +132 -42
  93. data/src/core/ext/load_reporting/load_reporting_filter.h +1 -0
  94. data/src/core/ext/resolver/dns/native/dns_resolver.c +88 -80
  95. data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +57 -102
  96. data/src/core/ext/transport/chttp2/alpn/alpn.c +1 -1
  97. data/src/core/ext/transport/chttp2/client/chttp2_connector.c +253 -0
  98. data/src/core/{lib/iomgr/ev_poll_and_epoll_posix.h → ext/transport/chttp2/client/chttp2_connector.h} +5 -5
  99. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +31 -160
  100. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c +5 -5
  101. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +44 -243
  102. data/src/core/ext/transport/chttp2/server/chttp2_server.c +342 -0
  103. data/src/core/ext/transport/chttp2/server/chttp2_server.h +47 -0
  104. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +11 -124
  105. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c +20 -9
  106. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +28 -236
  107. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +31 -27
  108. data/src/core/ext/transport/chttp2/transport/bin_decoder.h +5 -4
  109. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +25 -22
  110. data/src/core/ext/transport/chttp2/transport/bin_encoder.h +8 -7
  111. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +0 -3
  112. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +1345 -1521
  113. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -1
  114. data/src/core/ext/transport/chttp2/transport/frame.h +3 -5
  115. data/src/core/ext/transport/chttp2/transport/frame_data.c +50 -47
  116. data/src/core/ext/transport/chttp2/transport/frame_data.h +8 -9
  117. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +19 -21
  118. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +9 -8
  119. data/src/core/ext/transport/chttp2/transport/frame_ping.c +13 -12
  120. data/src/core/ext/transport/chttp2/transport/frame_ping.h +6 -6
  121. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +31 -19
  122. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +8 -7
  123. data/src/core/ext/transport/chttp2/transport/frame_settings.c +22 -25
  124. data/src/core/ext/transport/chttp2/transport/frame_settings.h +9 -8
  125. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +26 -18
  126. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +5 -6
  127. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +68 -58
  128. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +8 -5
  129. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +327 -214
  130. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +14 -9
  131. data/src/core/ext/transport/chttp2/transport/hpack_table.c +24 -19
  132. data/src/core/ext/transport/chttp2/transport/hpack_table.h +9 -6
  133. data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +2 -2
  134. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +1 -1
  135. data/src/core/ext/transport/chttp2/transport/internal.h +284 -436
  136. data/src/core/ext/transport/chttp2/transport/parsing.c +355 -590
  137. data/src/core/ext/transport/chttp2/transport/stream_lists.c +36 -309
  138. data/src/core/ext/transport/chttp2/transport/stream_map.c +13 -34
  139. data/src/core/ext/transport/chttp2/transport/stream_map.h +3 -4
  140. data/src/core/ext/transport/chttp2/transport/writing.c +174 -286
  141. data/src/core/lib/channel/channel_args.c +70 -13
  142. data/src/core/lib/channel/channel_args.h +28 -2
  143. data/src/core/lib/channel/channel_stack.c +77 -28
  144. data/src/core/lib/channel/channel_stack.h +61 -23
  145. data/src/core/lib/channel/channel_stack_builder.c +33 -25
  146. data/src/core/lib/channel/channel_stack_builder.h +17 -8
  147. data/src/core/lib/channel/compress_filter.c +52 -36
  148. data/src/core/lib/channel/connected_channel.c +20 -12
  149. data/src/core/lib/channel/connected_channel.h +2 -1
  150. data/src/core/lib/channel/context.h +13 -1
  151. data/src/core/lib/channel/deadline_filter.c +344 -0
  152. data/src/core/lib/channel/deadline_filter.h +99 -0
  153. data/src/core/lib/channel/handshaker.c +240 -0
  154. data/src/core/lib/channel/handshaker.h +164 -0
  155. data/src/core/lib/{security/credentials/google_default/credentials_windows.c → channel/handshaker_factory.c} +16 -23
  156. data/src/core/lib/channel/handshaker_factory.h +66 -0
  157. data/src/core/lib/channel/handshaker_registry.c +113 -0
  158. data/src/core/{ext/client_config/client_config.h → lib/channel/handshaker_registry.h} +26 -16
  159. data/src/core/lib/channel/http_client_filter.c +248 -46
  160. data/src/core/lib/channel/http_client_filter.h +3 -0
  161. data/src/core/lib/channel/http_server_filter.c +136 -24
  162. data/src/core/lib/channel/message_size_filter.c +261 -0
  163. data/src/core/lib/channel/message_size_filter.h +39 -0
  164. data/src/core/lib/compression/message_compress.c +43 -37
  165. data/src/core/lib/compression/message_compress.h +7 -5
  166. data/src/core/lib/http/format_request.c +26 -11
  167. data/src/core/lib/http/format_request.h +7 -5
  168. data/src/core/lib/http/httpcli.c +45 -27
  169. data/src/core/lib/http/httpcli.h +4 -4
  170. data/src/core/lib/http/httpcli_security_connector.c +56 -46
  171. data/src/core/lib/http/parser.c +17 -14
  172. data/src/core/lib/http/parser.h +4 -2
  173. data/src/core/lib/iomgr/closure.c +49 -7
  174. data/src/core/lib/iomgr/closure.h +56 -14
  175. data/src/core/lib/iomgr/combiner.c +422 -0
  176. data/src/core/lib/iomgr/combiner.h +64 -0
  177. data/src/core/lib/iomgr/endpoint.c +8 -2
  178. data/src/core/lib/iomgr/endpoint.h +17 -7
  179. data/src/core/lib/iomgr/endpoint_pair.h +3 -2
  180. data/src/core/lib/iomgr/endpoint_pair_posix.c +9 -8
  181. data/src/core/{ext/client_config/lb_policy_factory.c → lib/iomgr/endpoint_pair_uv.c} +18 -13
  182. data/src/core/lib/iomgr/endpoint_pair_windows.c +7 -6
  183. data/src/core/lib/iomgr/error.c +72 -6
  184. data/src/core/lib/iomgr/error.h +30 -3
  185. data/src/core/lib/iomgr/ev_epoll_linux.c +500 -382
  186. data/src/core/lib/iomgr/ev_epoll_linux.h +3 -2
  187. data/src/core/lib/iomgr/ev_poll_posix.c +317 -30
  188. data/src/core/lib/iomgr/ev_poll_posix.h +1 -0
  189. data/src/core/lib/iomgr/ev_posix.c +26 -5
  190. data/src/core/lib/iomgr/ev_posix.h +12 -1
  191. data/src/core/lib/iomgr/exec_ctx.c +27 -94
  192. data/src/core/lib/iomgr/exec_ctx.h +19 -22
  193. data/src/core/lib/iomgr/executor.c +29 -8
  194. data/src/core/lib/iomgr/executor.h +2 -4
  195. data/src/core/lib/iomgr/iocp_windows.c +3 -4
  196. data/src/core/lib/iomgr/iomgr.c +14 -10
  197. data/src/core/lib/iomgr/iomgr.h +6 -2
  198. data/src/core/lib/iomgr/iomgr_posix.c +2 -2
  199. data/src/core/lib/iomgr/iomgr_uv.c +49 -0
  200. data/src/core/lib/iomgr/iomgr_windows.c +2 -2
  201. data/src/core/lib/iomgr/load_file.c +3 -3
  202. data/src/core/lib/iomgr/load_file.h +2 -2
  203. data/src/core/lib/iomgr/network_status_tracker.c +1 -1
  204. data/src/core/lib/iomgr/pollset_set_uv.c +62 -0
  205. data/src/core/lib/iomgr/pollset_set_windows.c +3 -3
  206. data/src/core/lib/iomgr/pollset_uv.c +142 -0
  207. data/src/core/lib/iomgr/pollset_uv.h +42 -0
  208. data/src/core/lib/iomgr/pollset_windows.c +5 -6
  209. data/src/core/lib/iomgr/port.h +129 -0
  210. data/src/core/lib/iomgr/resolve_address.h +2 -1
  211. data/src/core/lib/iomgr/resolve_address_posix.c +14 -13
  212. data/src/core/lib/iomgr/resolve_address_uv.c +233 -0
  213. data/src/core/lib/iomgr/resolve_address_windows.c +14 -12
  214. data/src/core/lib/iomgr/resource_quota.c +832 -0
  215. data/src/core/lib/iomgr/resource_quota.h +159 -0
  216. data/src/core/lib/iomgr/sockaddr.h +10 -2
  217. data/src/core/lib/iomgr/sockaddr_utils.c +63 -36
  218. data/src/core/lib/iomgr/sockaddr_utils.h +14 -14
  219. data/src/core/lib/iomgr/socket_mutator.c +98 -0
  220. data/src/core/lib/iomgr/socket_mutator.h +80 -0
  221. data/src/core/lib/iomgr/socket_utils.h +42 -0
  222. data/src/core/lib/iomgr/socket_utils_common_posix.c +28 -13
  223. data/src/core/lib/iomgr/socket_utils_linux.c +11 -5
  224. data/src/core/lib/iomgr/socket_utils_posix.c +10 -7
  225. data/src/core/lib/iomgr/socket_utils_posix.h +11 -4
  226. data/src/core/lib/iomgr/socket_utils_uv.c +49 -0
  227. data/src/core/lib/iomgr/socket_utils_windows.c +52 -0
  228. data/src/core/lib/iomgr/socket_windows.c +14 -6
  229. data/src/core/lib/iomgr/socket_windows.h +1 -0
  230. data/src/core/lib/iomgr/tcp_client.h +8 -2
  231. data/src/core/lib/iomgr/tcp_client_posix.c +131 -82
  232. data/src/core/lib/iomgr/tcp_client_posix.h +45 -0
  233. data/src/core/lib/iomgr/tcp_client_uv.c +190 -0
  234. data/src/core/lib/iomgr/tcp_client_windows.c +54 -30
  235. data/src/core/lib/iomgr/tcp_posix.c +135 -56
  236. data/src/core/lib/iomgr/tcp_posix.h +2 -2
  237. data/src/core/lib/iomgr/tcp_server.h +14 -6
  238. data/src/core/lib/iomgr/tcp_server_posix.c +154 -118
  239. data/src/core/lib/iomgr/tcp_server_uv.c +388 -0
  240. data/src/core/lib/iomgr/tcp_server_windows.c +127 -100
  241. data/src/core/lib/iomgr/tcp_uv.c +367 -0
  242. data/src/core/lib/iomgr/tcp_uv.h +59 -0
  243. data/src/core/lib/iomgr/tcp_windows.c +65 -48
  244. data/src/core/lib/iomgr/tcp_windows.h +3 -1
  245. data/src/core/lib/iomgr/timer.h +21 -21
  246. data/src/core/lib/iomgr/{timer.c → timer_generic.c} +15 -10
  247. data/src/core/lib/iomgr/timer_generic.h +49 -0
  248. data/src/core/lib/iomgr/timer_heap.c +6 -0
  249. data/src/core/lib/iomgr/timer_uv.c +99 -0
  250. data/src/core/lib/iomgr/timer_uv.h +47 -0
  251. data/src/core/lib/iomgr/udp_server.c +116 -98
  252. data/src/core/lib/iomgr/udp_server.h +5 -3
  253. data/src/core/lib/iomgr/unix_sockets_posix.c +14 -6
  254. data/src/core/lib/iomgr/unix_sockets_posix.h +6 -5
  255. data/src/core/lib/iomgr/unix_sockets_posix_noop.c +4 -4
  256. data/src/core/lib/iomgr/wakeup_fd_cv.c +118 -0
  257. data/src/core/lib/iomgr/wakeup_fd_cv.h +80 -0
  258. data/src/core/lib/iomgr/wakeup_fd_eventfd.c +3 -3
  259. data/src/core/lib/iomgr/wakeup_fd_nospecial.c +3 -3
  260. data/src/core/lib/iomgr/wakeup_fd_pipe.c +12 -6
  261. data/src/core/lib/iomgr/wakeup_fd_posix.c +34 -5
  262. data/src/core/lib/iomgr/wakeup_fd_posix.h +5 -0
  263. data/src/core/lib/iomgr/workqueue.h +12 -20
  264. data/src/core/{ext/client_config/client_config.c → lib/iomgr/workqueue_uv.c} +24 -33
  265. data/{include/grpc/support/slice.h → src/core/lib/iomgr/workqueue_uv.h} +4 -6
  266. data/src/core/lib/iomgr/workqueue_windows.c +9 -8
  267. data/src/core/lib/json/json.c +3 -3
  268. data/src/core/lib/json/json.h +11 -11
  269. data/src/core/lib/json/json_reader.c +9 -5
  270. data/src/core/lib/profiling/basic_timers.c +10 -1
  271. data/src/core/lib/profiling/timers.h +2 -0
  272. data/src/core/lib/security/context/security_context.c +13 -3
  273. data/src/core/lib/security/context/security_context.h +20 -0
  274. data/src/core/lib/security/credentials/composite/composite_credentials.c +28 -14
  275. data/src/core/lib/security/credentials/composite/composite_credentials.h +2 -2
  276. data/src/core/lib/security/credentials/credentials.c +48 -19
  277. data/src/core/lib/security/credentials/credentials.h +36 -19
  278. data/src/core/lib/security/credentials/credentials_metadata.c +11 -8
  279. data/src/core/lib/security/credentials/fake/fake_credentials.c +15 -11
  280. data/src/core/lib/security/credentials/google_default/{credentials_posix.c → credentials_generic.c} +7 -14
  281. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +33 -21
  282. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +14 -0
  283. data/src/core/lib/security/credentials/iam/iam_credentials.c +3 -2
  284. data/src/core/lib/security/credentials/jwt/json_token.c +1 -0
  285. data/src/core/lib/security/credentials/jwt/json_token.h +1 -1
  286. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +54 -19
  287. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +2 -1
  288. data/src/core/lib/security/credentials/jwt/jwt_verifier.c +129 -79
  289. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +9 -6
  290. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +63 -28
  291. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +1 -1
  292. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +32 -11
  293. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +13 -9
  294. data/src/core/lib/security/transport/client_auth_filter.c +33 -27
  295. data/src/core/lib/security/transport/secure_endpoint.c +93 -68
  296. data/src/core/lib/security/transport/secure_endpoint.h +2 -2
  297. data/src/core/lib/security/transport/security_connector.c +133 -168
  298. data/src/core/lib/security/transport/security_connector.h +31 -46
  299. data/src/core/lib/security/transport/security_handshaker.c +501 -0
  300. data/src/core/lib/security/transport/{handshake.h → security_handshaker.h} +10 -10
  301. data/src/core/lib/security/transport/server_auth_filter.c +50 -38
  302. data/src/core/lib/security/util/b64.c +11 -8
  303. data/src/core/lib/security/util/b64.h +5 -4
  304. data/src/core/lib/slice/percent_encoding.c +182 -0
  305. data/src/core/lib/slice/percent_encoding.h +78 -0
  306. data/src/core/lib/{support → slice}/slice.c +81 -50
  307. data/src/core/lib/{support → slice}/slice_buffer.c +78 -60
  308. data/src/core/lib/slice/slice_internal.h +49 -0
  309. data/src/core/lib/slice/slice_string_helpers.c +90 -0
  310. data/src/core/lib/{iomgr/workqueue_posix.h → slice/slice_string_helpers.h} +18 -18
  311. data/src/core/lib/support/backoff.c +24 -13
  312. data/src/core/lib/support/backoff.h +5 -2
  313. data/src/core/lib/support/env.h +0 -2
  314. data/src/core/lib/support/log.c +5 -4
  315. data/src/core/lib/support/log_linux.c +0 -1
  316. data/src/core/lib/support/log_posix.c +1 -1
  317. data/src/core/lib/support/mpscq.c +83 -0
  318. data/src/core/lib/support/mpscq.h +65 -0
  319. data/src/core/lib/support/string.c +58 -49
  320. data/src/core/lib/support/string.h +11 -8
  321. data/src/core/lib/support/subprocess_posix.c +5 -2
  322. data/src/core/lib/support/thd.c +1 -1
  323. data/src/core/lib/support/time.c +43 -79
  324. data/src/core/lib/support/time_posix.c +1 -1
  325. data/src/core/lib/support/tmpfile.h +0 -2
  326. data/src/core/lib/surface/alarm.c +4 -1
  327. data/src/core/lib/surface/byte_buffer.c +17 -11
  328. data/src/core/lib/surface/byte_buffer_reader.c +23 -15
  329. data/src/core/lib/surface/call.c +294 -276
  330. data/src/core/lib/surface/call.h +24 -9
  331. data/src/core/lib/surface/call_log_batch.c +5 -3
  332. data/src/core/lib/surface/channel.c +127 -111
  333. data/src/core/lib/surface/channel.h +14 -5
  334. data/src/core/lib/surface/channel_init.c +1 -1
  335. data/src/core/lib/surface/channel_init.h +10 -1
  336. data/src/core/lib/surface/channel_ping.c +7 -6
  337. data/src/core/lib/surface/completion_queue.c +154 -18
  338. data/src/core/lib/surface/completion_queue.h +5 -0
  339. data/src/core/lib/surface/init.c +40 -6
  340. data/src/core/lib/surface/init.h +1 -0
  341. data/src/core/lib/surface/init_secure.c +5 -2
  342. data/src/core/lib/surface/lame_client.c +28 -18
  343. data/src/core/lib/surface/server.c +134 -87
  344. data/src/core/lib/surface/server.h +8 -0
  345. data/src/core/lib/surface/validate_metadata.c +1 -1
  346. data/src/core/lib/surface/version.c +3 -1
  347. data/src/core/lib/transport/byte_stream.c +7 -4
  348. data/src/core/lib/transport/byte_stream.h +6 -10
  349. data/src/core/lib/transport/connectivity_state.c +21 -12
  350. data/src/core/lib/transport/connectivity_state.h +4 -1
  351. data/src/core/lib/transport/mdstr_hash_table.c +118 -0
  352. data/src/core/lib/transport/mdstr_hash_table.h +77 -0
  353. data/src/core/lib/transport/metadata.c +83 -60
  354. data/src/core/lib/transport/metadata.h +41 -23
  355. data/src/core/lib/transport/metadata_batch.c +17 -11
  356. data/src/core/lib/transport/metadata_batch.h +20 -6
  357. data/src/core/lib/transport/pid_controller.c +57 -0
  358. data/src/core/lib/transport/pid_controller.h +64 -0
  359. data/src/core/lib/transport/service_config.c +251 -0
  360. data/src/core/lib/transport/service_config.h +71 -0
  361. data/src/core/lib/transport/static_metadata.c +18 -16
  362. data/src/core/lib/transport/static_metadata.h +113 -107
  363. data/src/core/{ext/transport/chttp2 → lib}/transport/timeout_encoding.c +3 -3
  364. data/src/core/{ext/transport/chttp2 → lib}/transport/timeout_encoding.h +7 -7
  365. data/src/core/lib/transport/transport.c +84 -23
  366. data/src/core/lib/transport/transport.h +53 -8
  367. data/src/core/lib/transport/transport_impl.h +3 -0
  368. data/src/core/lib/transport/transport_op_string.c +92 -20
  369. data/src/core/lib/tsi/ssl_transport_security.c +3 -1
  370. data/src/core/plugin_registry/grpc_plugin_registry.c +8 -4
  371. data/src/ruby/ext/grpc/extconf.rb +0 -1
  372. data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -7
  373. data/src/ruby/ext/grpc/rb_call.c +15 -5
  374. data/src/ruby/ext/grpc/rb_channel.c +1 -1
  375. data/src/ruby/ext/grpc/rb_compression_options.c +466 -0
  376. data/src/{core/ext/client_config/default_initial_connect_string.c → ruby/ext/grpc/rb_compression_options.h} +10 -5
  377. data/src/ruby/ext/grpc/rb_grpc.c +3 -1
  378. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +198 -190
  379. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +306 -294
  380. data/src/ruby/ext/grpc/rb_server.c +18 -12
  381. data/src/ruby/lib/grpc/errors.rb +154 -2
  382. data/src/ruby/lib/grpc/generic/active_call.rb +144 -63
  383. data/src/ruby/lib/grpc/generic/bidi_call.rb +18 -2
  384. data/src/ruby/lib/grpc/generic/client_stub.rb +7 -5
  385. data/src/ruby/lib/grpc/generic/rpc_desc.rb +39 -13
  386. data/src/ruby/lib/grpc/generic/rpc_server.rb +51 -24
  387. data/src/ruby/lib/grpc/generic/service.rb +3 -2
  388. data/src/ruby/lib/grpc/version.rb +1 -1
  389. data/src/ruby/pb/grpc/health/checker.rb +3 -1
  390. data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +7 -0
  391. data/src/ruby/pb/test/client.rb +307 -7
  392. data/src/ruby/pb/test/server.rb +26 -1
  393. data/src/ruby/spec/compression_options_spec.rb +164 -0
  394. data/src/ruby/spec/error_sanity_spec.rb +64 -0
  395. data/src/ruby/spec/generic/active_call_spec.rb +290 -12
  396. data/src/ruby/spec/generic/client_stub_spec.rb +91 -41
  397. data/src/ruby/spec/generic/rpc_desc_spec.rb +36 -16
  398. data/src/ruby/spec/generic/rpc_server_pool_spec.rb +22 -28
  399. data/src/ruby/spec/generic/rpc_server_spec.rb +6 -6
  400. data/src/ruby/spec/pb/health/checker_spec.rb +27 -19
  401. data/src/ruby/spec/spec_helper.rb +2 -0
  402. data/third_party/boringssl/crypto/aes/aes.c +12 -12
  403. data/third_party/boringssl/crypto/aes/mode_wrappers.c +6 -2
  404. data/third_party/boringssl/crypto/asn1/a_d2i_fp.c +28 -13
  405. data/third_party/boringssl/crypto/asn1/a_gentm.c +2 -0
  406. data/third_party/boringssl/crypto/asn1/a_object.c +7 -3
  407. data/third_party/boringssl/crypto/asn1/a_strnid.c +1 -0
  408. data/third_party/boringssl/crypto/asn1/a_time.c +0 -11
  409. data/third_party/boringssl/crypto/asn1/a_type.c +0 -2
  410. data/third_party/boringssl/crypto/asn1/a_utctm.c +1 -30
  411. data/third_party/boringssl/crypto/asn1/asn1_lib.c +56 -76
  412. data/third_party/boringssl/crypto/asn1/asn1_locl.h +0 -10
  413. data/third_party/boringssl/crypto/asn1/asn1_par.c +0 -322
  414. data/third_party/boringssl/crypto/asn1/f_enum.c +1 -108
  415. data/third_party/boringssl/crypto/asn1/f_int.c +1 -106
  416. data/third_party/boringssl/crypto/asn1/f_string.c +1 -106
  417. data/third_party/boringssl/crypto/asn1/tasn_dec.c +10 -14
  418. data/third_party/boringssl/crypto/asn1/tasn_enc.c +17 -11
  419. data/third_party/boringssl/crypto/asn1/tasn_typ.c +29 -42
  420. data/third_party/boringssl/crypto/asn1/tasn_utl.c +1 -1
  421. data/third_party/boringssl/crypto/base64/base64.c +249 -285
  422. data/third_party/boringssl/crypto/bio/bio.c +13 -23
  423. data/third_party/boringssl/crypto/bio/bio_mem.c +3 -2
  424. data/third_party/boringssl/crypto/bio/connect.c +12 -3
  425. data/third_party/boringssl/crypto/bio/fd.c +22 -15
  426. data/third_party/boringssl/crypto/bio/file.c +2 -38
  427. data/third_party/boringssl/crypto/bio/hexdump.c +1 -2
  428. data/third_party/boringssl/crypto/bio/internal.h +3 -0
  429. data/third_party/boringssl/crypto/bio/pair.c +1 -1
  430. data/third_party/boringssl/crypto/bio/socket.c +10 -2
  431. data/third_party/boringssl/crypto/bio/socket_helper.c +2 -2
  432. data/third_party/boringssl/crypto/bn/asm/x86_64-gcc.c +0 -8
  433. data/third_party/boringssl/crypto/bn/bn.c +38 -0
  434. data/third_party/boringssl/crypto/bn/cmp.c +25 -0
  435. data/third_party/boringssl/crypto/bn/convert.c +73 -76
  436. data/third_party/boringssl/crypto/bn/div.c +136 -70
  437. data/third_party/boringssl/crypto/bn/exponentiation.c +86 -381
  438. data/third_party/boringssl/crypto/bn/gcd.c +213 -296
  439. data/third_party/boringssl/crypto/bn/generic.c +0 -80
  440. data/third_party/boringssl/crypto/bn/internal.h +15 -3
  441. data/third_party/boringssl/crypto/bn/montgomery.c +57 -207
  442. data/third_party/boringssl/crypto/bn/montgomery_inv.c +160 -0
  443. data/third_party/boringssl/crypto/bn/mul.c +2 -1
  444. data/third_party/boringssl/crypto/bn/prime.c +24 -8
  445. data/third_party/boringssl/crypto/bn/random.c +47 -33
  446. data/third_party/boringssl/crypto/bn/sqrt.c +4 -5
  447. data/third_party/boringssl/crypto/buf/buf.c +25 -21
  448. data/third_party/boringssl/crypto/bytestring/ber.c +1 -0
  449. data/third_party/boringssl/crypto/bytestring/cbb.c +50 -22
  450. data/third_party/boringssl/crypto/bytestring/cbs.c +28 -4
  451. data/third_party/boringssl/crypto/chacha/{chacha_generic.c → chacha.c} +56 -29
  452. data/third_party/boringssl/crypto/cipher/aead.c +11 -22
  453. data/third_party/boringssl/crypto/cipher/cipher.c +2 -2
  454. data/third_party/boringssl/crypto/cipher/e_aes.c +53 -103
  455. data/third_party/boringssl/crypto/cipher/e_chacha20poly1305.c +2 -8
  456. data/third_party/boringssl/crypto/cipher/e_des.c +3 -5
  457. data/third_party/boringssl/crypto/cipher/e_null.c +1 -1
  458. data/third_party/boringssl/crypto/cipher/e_rc2.c +1 -1
  459. data/third_party/boringssl/crypto/cipher/e_rc4.c +1 -1
  460. data/third_party/boringssl/crypto/cipher/e_ssl3.c +3 -63
  461. data/third_party/boringssl/crypto/cipher/e_tls.c +12 -83
  462. data/third_party/boringssl/crypto/cipher/internal.h +8 -10
  463. data/third_party/boringssl/crypto/cipher/tls_cbc.c +69 -40
  464. data/third_party/boringssl/crypto/conf/conf.c +2 -1
  465. data/third_party/boringssl/crypto/cpu-aarch64-linux.c +61 -0
  466. data/third_party/boringssl/crypto/cpu-arm-linux.c +360 -0
  467. data/third_party/boringssl/crypto/cpu-arm.c +0 -161
  468. data/third_party/boringssl/crypto/cpu-intel.c +5 -3
  469. data/third_party/boringssl/{ssl/test/scoped_types.h → crypto/cpu-ppc64le.c} +21 -9
  470. data/third_party/boringssl/crypto/crypto.c +29 -7
  471. data/third_party/boringssl/crypto/curve25519/curve25519.c +284 -242
  472. data/third_party/boringssl/crypto/curve25519/internal.h +64 -0
  473. data/third_party/boringssl/crypto/curve25519/spake25519.c +464 -0
  474. data/third_party/boringssl/crypto/curve25519/x25519-x86_64.c +21 -0
  475. data/third_party/boringssl/crypto/dh/check.c +22 -6
  476. data/third_party/boringssl/crypto/dh/dh.c +45 -21
  477. data/third_party/boringssl/crypto/dh/dh_asn1.c +96 -20
  478. data/third_party/boringssl/crypto/dh/params.c +30 -78
  479. data/third_party/boringssl/crypto/digest/digest.c +3 -3
  480. data/third_party/boringssl/crypto/dsa/dsa.c +59 -29
  481. data/third_party/boringssl/crypto/dsa/dsa_asn1.c +4 -0
  482. data/third_party/boringssl/crypto/ec/ec.c +84 -140
  483. data/third_party/boringssl/crypto/ec/ec_asn1.c +82 -52
  484. data/third_party/boringssl/crypto/ec/ec_key.c +15 -15
  485. data/third_party/boringssl/crypto/ec/ec_montgomery.c +87 -50
  486. data/third_party/boringssl/crypto/ec/internal.h +12 -36
  487. data/third_party/boringssl/crypto/ec/oct.c +11 -11
  488. data/third_party/boringssl/crypto/ec/p224-64.c +59 -116
  489. data/third_party/boringssl/crypto/ec/p256-64.c +88 -163
  490. data/third_party/boringssl/crypto/ec/p256-x86_64.c +46 -58
  491. data/third_party/boringssl/crypto/ec/simple.c +81 -201
  492. data/third_party/boringssl/crypto/ec/util-64.c +0 -74
  493. data/third_party/boringssl/crypto/ecdh/ecdh.c +7 -1
  494. data/third_party/boringssl/crypto/ecdsa/ecdsa.c +28 -46
  495. data/third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c +1 -0
  496. data/third_party/boringssl/crypto/engine/engine.c +1 -1
  497. data/third_party/boringssl/crypto/err/err.c +3 -3
  498. data/third_party/boringssl/crypto/evp/evp.c +14 -59
  499. data/third_party/boringssl/crypto/evp/evp_asn1.c +144 -87
  500. data/third_party/boringssl/crypto/evp/evp_ctx.c +7 -7
  501. data/third_party/boringssl/crypto/evp/internal.h +4 -46
  502. data/third_party/boringssl/crypto/evp/p_dsa_asn1.c +8 -157
  503. data/third_party/boringssl/crypto/evp/p_ec.c +1 -1
  504. data/third_party/boringssl/crypto/evp/p_ec_asn1.c +22 -170
  505. data/third_party/boringssl/crypto/evp/p_rsa.c +1 -1
  506. data/third_party/boringssl/crypto/evp/p_rsa_asn1.c +10 -548
  507. data/third_party/boringssl/crypto/evp/print.c +520 -0
  508. data/third_party/boringssl/crypto/ex_data.c +4 -6
  509. data/third_party/boringssl/crypto/hkdf/hkdf.c +38 -17
  510. data/third_party/boringssl/crypto/hmac/hmac.c +6 -6
  511. data/third_party/boringssl/crypto/internal.h +57 -77
  512. data/third_party/boringssl/crypto/lhash/lhash.c +6 -10
  513. data/third_party/boringssl/crypto/md4/md4.c +9 -0
  514. data/third_party/boringssl/crypto/mem.c +19 -19
  515. data/third_party/boringssl/crypto/modes/cfb.c +5 -6
  516. data/third_party/boringssl/crypto/modes/ctr.c +10 -18
  517. data/third_party/boringssl/crypto/modes/gcm.c +100 -66
  518. data/third_party/boringssl/crypto/modes/internal.h +15 -27
  519. data/third_party/boringssl/crypto/modes/ofb.c +9 -22
  520. data/third_party/boringssl/crypto/newhope/error_correction.c +131 -0
  521. data/third_party/boringssl/crypto/newhope/internal.h +71 -0
  522. data/third_party/boringssl/crypto/newhope/newhope.c +174 -0
  523. data/third_party/boringssl/crypto/newhope/ntt.c +148 -0
  524. data/third_party/boringssl/crypto/newhope/poly.c +183 -0
  525. data/third_party/boringssl/crypto/newhope/precomp.c +306 -0
  526. data/third_party/boringssl/crypto/newhope/reduce.c +42 -0
  527. data/third_party/boringssl/crypto/obj/obj.c +111 -135
  528. data/third_party/boringssl/crypto/obj/obj_dat.h +4 -10
  529. data/third_party/boringssl/crypto/pem/pem_lib.c +6 -43
  530. data/third_party/boringssl/crypto/pem/pem_pkey.c +10 -19
  531. data/third_party/boringssl/crypto/pkcs8/p5_pbe.c +1 -0
  532. data/third_party/boringssl/crypto/pkcs8/p5_pbev2.c +2 -1
  533. data/third_party/boringssl/crypto/pkcs8/p8_pkey.c +2 -2
  534. data/third_party/boringssl/crypto/pkcs8/pkcs8.c +95 -87
  535. data/third_party/boringssl/crypto/{test/test_util.h → poly1305/internal.h} +15 -10
  536. data/third_party/boringssl/crypto/poly1305/poly1305.c +8 -15
  537. data/third_party/boringssl/crypto/poly1305/poly1305_arm.c +1 -0
  538. data/third_party/boringssl/crypto/poly1305/poly1305_vec.c +3 -3
  539. data/third_party/boringssl/crypto/rand/deterministic.c +47 -0
  540. data/third_party/boringssl/crypto/rand/rand.c +4 -1
  541. data/third_party/boringssl/crypto/rand/urandom.c +5 -7
  542. data/third_party/boringssl/crypto/rand/windows.c +5 -8
  543. data/third_party/boringssl/crypto/rc4/rc4.c +24 -209
  544. data/third_party/boringssl/crypto/refcount_lock.c +2 -2
  545. data/third_party/boringssl/crypto/rsa/blinding.c +74 -232
  546. data/third_party/boringssl/crypto/rsa/internal.h +5 -13
  547. data/third_party/boringssl/crypto/rsa/padding.c +64 -63
  548. data/third_party/boringssl/crypto/rsa/rsa.c +50 -28
  549. data/third_party/boringssl/crypto/rsa/rsa_asn1.c +8 -16
  550. data/third_party/boringssl/crypto/rsa/rsa_impl.c +134 -122
  551. data/third_party/boringssl/crypto/sha/sha256.c +2 -2
  552. data/third_party/boringssl/crypto/sha/sha512.c +7 -7
  553. data/third_party/boringssl/crypto/stack/stack.c +13 -22
  554. data/third_party/boringssl/crypto/thread.c +21 -12
  555. data/third_party/boringssl/crypto/thread_none.c +6 -2
  556. data/third_party/boringssl/crypto/thread_pthread.c +16 -7
  557. data/third_party/boringssl/crypto/thread_win.c +38 -85
  558. data/third_party/boringssl/crypto/x509/a_sign.c +3 -3
  559. data/third_party/boringssl/crypto/x509/a_strex.c +1 -1
  560. data/third_party/boringssl/crypto/x509/a_verify.c +2 -2
  561. data/third_party/boringssl/crypto/{evp → x509}/algorithm.c +37 -53
  562. data/third_party/boringssl/crypto/x509/asn1_gen.c +1 -2
  563. data/third_party/boringssl/crypto/x509/by_dir.c +6 -6
  564. data/third_party/boringssl/crypto/x509/internal.h +66 -0
  565. data/third_party/boringssl/crypto/x509/rsa_pss.c +385 -0
  566. data/third_party/boringssl/crypto/x509/t_x509.c +10 -12
  567. data/third_party/boringssl/crypto/x509/x509.c +5 -0
  568. data/third_party/boringssl/crypto/x509/x509_att.c +9 -3
  569. data/third_party/boringssl/crypto/x509/x509_lu.c +34 -44
  570. data/third_party/boringssl/crypto/x509/x509_obj.c +19 -2
  571. data/third_party/boringssl/crypto/x509/x509_r2x.c +9 -5
  572. data/third_party/boringssl/crypto/x509/x509_set.c +5 -0
  573. data/third_party/boringssl/crypto/x509/x509_txt.c +5 -0
  574. data/third_party/boringssl/crypto/x509/x509_vfy.c +63 -32
  575. data/third_party/boringssl/crypto/x509/x509_vpm.c +29 -18
  576. data/third_party/boringssl/crypto/x509/x509cset.c +2 -1
  577. data/third_party/boringssl/crypto/x509/x_crl.c +2 -2
  578. data/third_party/boringssl/crypto/x509/x_name.c +14 -17
  579. data/third_party/boringssl/crypto/x509/x_pubkey.c +10 -7
  580. data/third_party/boringssl/crypto/x509/x_x509.c +67 -6
  581. data/third_party/boringssl/crypto/x509v3/pcy_cache.c +2 -2
  582. data/third_party/boringssl/crypto/x509v3/pcy_tree.c +2 -1
  583. data/third_party/boringssl/crypto/x509v3/v3_conf.c +4 -3
  584. data/third_party/boringssl/crypto/x509v3/v3_cpols.c +5 -0
  585. data/third_party/boringssl/crypto/x509v3/v3_prn.c +0 -3
  586. data/third_party/boringssl/crypto/x509v3/v3_purp.c +2 -2
  587. data/third_party/boringssl/crypto/x509v3/v3_utl.c +2 -1
  588. data/third_party/boringssl/include/openssl/aead.h +72 -73
  589. data/third_party/boringssl/include/openssl/arm_arch.h +0 -6
  590. data/third_party/boringssl/include/openssl/asn1.h +103 -235
  591. data/third_party/boringssl/include/openssl/asn1_mac.h +17 -74
  592. data/third_party/boringssl/include/openssl/asn1t.h +1 -11
  593. data/third_party/boringssl/include/openssl/base.h +145 -3
  594. data/third_party/boringssl/include/openssl/base64.h +20 -17
  595. data/third_party/boringssl/include/openssl/bio.h +59 -34
  596. data/third_party/boringssl/include/openssl/bn.h +118 -51
  597. data/third_party/boringssl/include/openssl/buf.h +15 -0
  598. data/third_party/boringssl/include/openssl/bytestring.h +52 -4
  599. data/third_party/boringssl/include/openssl/chacha.h +2 -2
  600. data/third_party/boringssl/include/openssl/cipher.h +18 -1
  601. data/third_party/boringssl/include/openssl/cmac.h +11 -0
  602. data/third_party/boringssl/include/openssl/conf.h +13 -2
  603. data/third_party/boringssl/include/openssl/cpu.h +20 -23
  604. data/third_party/boringssl/include/openssl/crypto.h +22 -1
  605. data/third_party/boringssl/include/openssl/curve25519.h +96 -4
  606. data/third_party/boringssl/include/openssl/dh.h +71 -16
  607. data/third_party/boringssl/include/openssl/digest.h +38 -11
  608. data/third_party/boringssl/include/openssl/dsa.h +40 -4
  609. data/third_party/boringssl/include/openssl/ec.h +44 -18
  610. data/third_party/boringssl/include/openssl/ec_key.h +27 -6
  611. data/third_party/boringssl/include/openssl/ecdsa.h +11 -0
  612. data/third_party/boringssl/include/openssl/engine.h +11 -0
  613. data/third_party/boringssl/include/openssl/evp.h +52 -88
  614. data/third_party/boringssl/include/openssl/hkdf.h +24 -4
  615. data/third_party/boringssl/include/openssl/hmac.h +20 -6
  616. data/third_party/boringssl/include/openssl/md4.h +4 -0
  617. data/third_party/boringssl/include/openssl/mem.h +19 -0
  618. data/third_party/boringssl/include/openssl/newhope.h +158 -0
  619. data/third_party/boringssl/include/openssl/nid.h +4166 -0
  620. data/third_party/boringssl/include/openssl/obj.h +31 -3
  621. data/third_party/boringssl/include/openssl/obj_mac.h +17 -4143
  622. data/third_party/boringssl/include/openssl/{opensslfeatures.h → opensslconf.h} +3 -3
  623. data/third_party/boringssl/include/openssl/pem.h +5 -0
  624. data/third_party/boringssl/include/openssl/pkcs8.h +12 -0
  625. data/third_party/boringssl/include/openssl/rand.h +6 -0
  626. data/third_party/boringssl/include/openssl/rc4.h +6 -0
  627. data/third_party/boringssl/{crypto/dh/internal.h → include/openssl/ripemd.h} +38 -11
  628. data/third_party/boringssl/include/openssl/rsa.h +127 -65
  629. data/third_party/boringssl/include/openssl/sha.h +14 -10
  630. data/third_party/boringssl/include/openssl/ssl.h +561 -275
  631. data/third_party/boringssl/include/openssl/ssl3.h +18 -25
  632. data/third_party/boringssl/include/openssl/stack.h +2 -4
  633. data/third_party/boringssl/include/openssl/stack_macros.h +321 -353
  634. data/third_party/boringssl/include/openssl/thread.h +31 -13
  635. data/third_party/boringssl/include/openssl/time_support.h +1 -0
  636. data/third_party/boringssl/include/openssl/tls1.h +37 -33
  637. data/third_party/boringssl/include/openssl/x509.h +69 -26
  638. data/third_party/boringssl/include/openssl/x509_vfy.h +12 -10
  639. data/third_party/boringssl/include/openssl/x509v3.h +23 -2
  640. data/third_party/boringssl/ssl/custom_extensions.c +3 -5
  641. data/third_party/boringssl/ssl/d1_both.c +463 -499
  642. data/third_party/boringssl/ssl/d1_lib.c +38 -109
  643. data/third_party/boringssl/ssl/d1_pkt.c +173 -334
  644. data/third_party/boringssl/ssl/d1_srtp.c +20 -18
  645. data/third_party/boringssl/ssl/{d1_meth.c → dtls_method.c} +88 -15
  646. data/third_party/boringssl/ssl/dtls_record.c +27 -26
  647. data/third_party/boringssl/ssl/{s3_clnt.c → handshake_client.c} +816 -904
  648. data/third_party/boringssl/ssl/handshake_server.c +1932 -0
  649. data/third_party/boringssl/ssl/internal.h +712 -439
  650. data/third_party/boringssl/ssl/s3_both.c +445 -257
  651. data/third_party/boringssl/ssl/s3_enc.c +53 -36
  652. data/third_party/boringssl/ssl/s3_lib.c +23 -268
  653. data/third_party/boringssl/ssl/s3_pkt.c +168 -364
  654. data/third_party/boringssl/ssl/ssl_aead_ctx.c +46 -17
  655. data/third_party/boringssl/ssl/ssl_asn1.c +56 -26
  656. data/third_party/boringssl/ssl/ssl_buffer.c +16 -24
  657. data/third_party/boringssl/ssl/ssl_cert.c +324 -49
  658. data/third_party/boringssl/ssl/ssl_cipher.c +205 -150
  659. data/third_party/boringssl/ssl/ssl_ecdh.c +287 -51
  660. data/third_party/boringssl/ssl/ssl_file.c +21 -68
  661. data/third_party/boringssl/ssl/ssl_lib.c +881 -510
  662. data/third_party/boringssl/ssl/ssl_rsa.c +404 -34
  663. data/third_party/boringssl/ssl/ssl_session.c +324 -103
  664. data/third_party/boringssl/ssl/ssl_stat.c +6 -88
  665. data/third_party/boringssl/ssl/t1_enc.c +23 -39
  666. data/third_party/boringssl/ssl/t1_lib.c +1120 -622
  667. data/third_party/boringssl/ssl/tls13_both.c +440 -0
  668. data/third_party/boringssl/ssl/tls13_client.c +682 -0
  669. data/third_party/boringssl/ssl/tls13_enc.c +391 -0
  670. data/third_party/boringssl/ssl/tls13_server.c +672 -0
  671. data/third_party/boringssl/ssl/{s3_meth.c → tls_method.c} +100 -21
  672. data/third_party/boringssl/ssl/tls_record.c +159 -77
  673. data/third_party/nanopb/pb.h +60 -28
  674. data/third_party/nanopb/pb_decode.c +120 -92
  675. data/third_party/nanopb/pb_decode.h +3 -3
  676. data/third_party/nanopb/pb_encode.c +73 -67
  677. data/third_party/nanopb/pb_encode.h +4 -4
  678. metadata +155 -89
  679. data/include/grpc/impl/codegen/byte_buffer.h +0 -122
  680. data/include/grpc/impl/codegen/log.h +0 -118
  681. data/include/grpc/impl/codegen/time.h +0 -130
  682. data/src/core/ext/client_config/client_channel.c +0 -593
  683. data/src/core/ext/client_config/subchannel_call_holder.c +0 -272
  684. data/src/core/ext/client_config/subchannel_call_holder.h +0 -99
  685. data/src/core/lib/iomgr/ev_poll_and_epoll_posix.c +0 -2046
  686. data/src/core/lib/iomgr/workqueue_posix.c +0 -151
  687. data/src/core/lib/security/transport/handshake.c +0 -368
  688. data/third_party/boringssl/crypto/asn1/a_bytes.c +0 -308
  689. data/third_party/boringssl/crypto/asn1/bio_asn1.c +0 -477
  690. data/third_party/boringssl/crypto/asn1/bio_ndef.c +0 -251
  691. data/third_party/boringssl/crypto/asn1/t_pkey.c +0 -110
  692. data/third_party/boringssl/crypto/asn1/tasn_prn.c +0 -596
  693. data/third_party/boringssl/crypto/chacha/chacha_vec.c +0 -328
  694. data/third_party/boringssl/crypto/directory.h +0 -66
  695. data/third_party/boringssl/crypto/directory_posix.c +0 -108
  696. data/third_party/boringssl/crypto/directory_win.c +0 -144
  697. data/third_party/boringssl/crypto/test/scoped_types.h +0 -140
  698. data/third_party/boringssl/include/openssl/pqueue.h +0 -146
  699. data/third_party/boringssl/ssl/d1_clnt.c +0 -561
  700. data/third_party/boringssl/ssl/d1_srvr.c +0 -476
  701. data/third_party/boringssl/ssl/pqueue/pqueue.c +0 -197
  702. data/third_party/boringssl/ssl/s3_srvr.c +0 -2272
  703. data/third_party/boringssl/ssl/test/async_bio.h +0 -45
  704. data/third_party/boringssl/ssl/test/packeted_bio.h +0 -44
  705. data/third_party/boringssl/ssl/test/test_config.h +0 -110
@@ -34,7 +34,7 @@
34
34
  #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H
35
35
  #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H
36
36
 
37
- #include <grpc/support/slice.h>
37
+ #include <grpc/slice.h>
38
38
  #include <stdbool.h>
39
39
 
40
40
  struct grpc_base64_decode_context {
@@ -55,12 +55,13 @@ bool grpc_base64_decode_partial(struct grpc_base64_decode_context *ctx);
55
55
 
56
56
  /* base64 decode a slice with pad chars. Returns a new slice, does not take
57
57
  ownership of the input. Returns an empty slice if decoding is failed. */
58
- gpr_slice grpc_chttp2_base64_decode(gpr_slice input);
58
+ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx, grpc_slice input);
59
59
 
60
60
  /* base64 decode a slice without pad chars, data length is needed. Returns a new
61
61
  slice, does not take ownership of the input. Returns an empty slice if
62
62
  decoding is failed. */
63
- gpr_slice grpc_chttp2_base64_decode_with_length(gpr_slice input,
64
- size_t output_length);
63
+ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
64
+ grpc_slice input,
65
+ size_t output_length);
65
66
 
66
67
  #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */
@@ -61,14 +61,14 @@ static const b64_huff_sym huff_alphabet[64] = {
61
61
 
62
62
  static const uint8_t tail_xtra[3] = {0, 2, 3};
63
63
 
64
- gpr_slice grpc_chttp2_base64_encode(gpr_slice input) {
65
- size_t input_length = GPR_SLICE_LENGTH(input);
64
+ grpc_slice grpc_chttp2_base64_encode(grpc_slice input) {
65
+ size_t input_length = GRPC_SLICE_LENGTH(input);
66
66
  size_t input_triplets = input_length / 3;
67
67
  size_t tail_case = input_length % 3;
68
68
  size_t output_length = input_triplets * 4 + tail_xtra[tail_case];
69
- gpr_slice output = gpr_slice_malloc(output_length);
70
- uint8_t *in = GPR_SLICE_START_PTR(input);
71
- char *out = (char *)GPR_SLICE_START_PTR(output);
69
+ grpc_slice output = grpc_slice_malloc(output_length);
70
+ uint8_t *in = GRPC_SLICE_START_PTR(input);
71
+ char *out = (char *)GRPC_SLICE_START_PTR(output);
72
72
  size_t i;
73
73
 
74
74
  /* encode full triplets */
@@ -100,27 +100,29 @@ gpr_slice grpc_chttp2_base64_encode(gpr_slice input) {
100
100
  break;
101
101
  }
102
102
 
103
- GPR_ASSERT(out == (char *)GPR_SLICE_END_PTR(output));
104
- GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
103
+ GPR_ASSERT(out == (char *)GRPC_SLICE_END_PTR(output));
104
+ GPR_ASSERT(in == GRPC_SLICE_END_PTR(input));
105
105
  return output;
106
106
  }
107
107
 
108
- gpr_slice grpc_chttp2_huffman_compress(gpr_slice input) {
108
+ grpc_slice grpc_chttp2_huffman_compress(grpc_slice input) {
109
109
  size_t nbits;
110
110
  uint8_t *in;
111
111
  uint8_t *out;
112
- gpr_slice output;
112
+ grpc_slice output;
113
113
  uint32_t temp = 0;
114
114
  uint32_t temp_length = 0;
115
115
 
116
116
  nbits = 0;
117
- for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
117
+ for (in = GRPC_SLICE_START_PTR(input); in != GRPC_SLICE_END_PTR(input);
118
+ ++in) {
118
119
  nbits += grpc_chttp2_huffsyms[*in].length;
119
120
  }
120
121
 
121
- output = gpr_slice_malloc(nbits / 8 + (nbits % 8 != 0));
122
- out = GPR_SLICE_START_PTR(output);
123
- for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
122
+ output = grpc_slice_malloc(nbits / 8 + (nbits % 8 != 0));
123
+ out = GRPC_SLICE_START_PTR(output);
124
+ for (in = GRPC_SLICE_START_PTR(input); in != GRPC_SLICE_END_PTR(input);
125
+ ++in) {
124
126
  int sym = *in;
125
127
  temp <<= grpc_chttp2_huffsyms[sym].length;
126
128
  temp |= grpc_chttp2_huffsyms[sym].bits;
@@ -141,7 +143,7 @@ gpr_slice grpc_chttp2_huffman_compress(gpr_slice input) {
141
143
  (uint8_t)(0xffu >> temp_length));
142
144
  }
143
145
 
144
- GPR_ASSERT(out == GPR_SLICE_END_PTR(output));
146
+ GPR_ASSERT(out == GRPC_SLICE_END_PTR(output));
145
147
 
146
148
  return output;
147
149
  }
@@ -175,16 +177,17 @@ static void enc_add1(huff_out *out, uint8_t a) {
175
177
  enc_flush_some(out);
176
178
  }
177
179
 
178
- gpr_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(gpr_slice input) {
179
- size_t input_length = GPR_SLICE_LENGTH(input);
180
+ grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
181
+ grpc_slice input) {
182
+ size_t input_length = GRPC_SLICE_LENGTH(input);
180
183
  size_t input_triplets = input_length / 3;
181
184
  size_t tail_case = input_length % 3;
182
185
  size_t output_syms = input_triplets * 4 + tail_xtra[tail_case];
183
186
  size_t max_output_bits = 11 * output_syms;
184
187
  size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0);
185
- gpr_slice output = gpr_slice_malloc(max_output_length);
186
- uint8_t *in = GPR_SLICE_START_PTR(input);
187
- uint8_t *start_out = GPR_SLICE_START_PTR(output);
188
+ grpc_slice output = grpc_slice_malloc(max_output_length);
189
+ uint8_t *in = GRPC_SLICE_START_PTR(input);
190
+ uint8_t *start_out = GRPC_SLICE_START_PTR(output);
188
191
  huff_out out;
189
192
  size_t i;
190
193
 
@@ -231,9 +234,9 @@ gpr_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(gpr_slice input) {
231
234
  (uint8_t)(0xffu >> out.temp_length));
232
235
  }
233
236
 
234
- GPR_ASSERT(out.out <= GPR_SLICE_END_PTR(output));
235
- GPR_SLICE_SET_LENGTH(output, out.out - start_out);
237
+ GPR_ASSERT(out.out <= GRPC_SLICE_END_PTR(output));
238
+ GRPC_SLICE_SET_LENGTH(output, out.out - start_out);
236
239
 
237
- GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
240
+ GPR_ASSERT(in == GRPC_SLICE_END_PTR(input));
238
241
  return output;
239
242
  }
@@ -34,21 +34,22 @@
34
34
  #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H
35
35
  #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H
36
36
 
37
- #include <grpc/support/slice.h>
37
+ #include <grpc/slice.h>
38
38
 
39
39
  /* base64 encode a slice. Returns a new slice, does not take ownership of the
40
40
  input */
41
- gpr_slice grpc_chttp2_base64_encode(gpr_slice input);
41
+ grpc_slice grpc_chttp2_base64_encode(grpc_slice input);
42
42
 
43
43
  /* Compress a slice with the static huffman encoder detailed in the hpack
44
44
  standard. Returns a new slice, does not take ownership of the input */
45
- gpr_slice grpc_chttp2_huffman_compress(gpr_slice input);
45
+ grpc_slice grpc_chttp2_huffman_compress(grpc_slice input);
46
46
 
47
47
  /* equivalent to:
48
- gpr_slice x = grpc_chttp2_base64_encode(input);
49
- gpr_slice y = grpc_chttp2_huffman_compress(x);
50
- gpr_slice_unref(x);
48
+ grpc_slice x = grpc_chttp2_base64_encode(input);
49
+ grpc_slice y = grpc_chttp2_huffman_compress(x);
50
+ grpc_slice_unref_internal(exec_ctx, x);
51
51
  return y; */
52
- gpr_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(gpr_slice input);
52
+ grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
53
+ grpc_slice input);
53
54
 
54
55
  #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */
@@ -36,14 +36,11 @@
36
36
  #include "src/core/lib/debug/trace.h"
37
37
  #include "src/core/lib/transport/metadata.h"
38
38
 
39
- extern int grpc_http_write_state_trace;
40
-
41
39
  void grpc_chttp2_plugin_init(void) {
42
40
  grpc_chttp2_base64_encode_and_huffman_compress =
43
41
  grpc_chttp2_base64_encode_and_huffman_compress_impl;
44
42
  grpc_register_tracer("http", &grpc_http_trace);
45
43
  grpc_register_tracer("flowctl", &grpc_flowctl_trace);
46
- grpc_register_tracer("http_write_state", &grpc_http_write_state_trace);
47
44
  }
48
45
 
49
46
  void grpc_chttp2_plugin_shutdown(void) {}
@@ -33,128 +33,95 @@
33
33
 
34
34
  #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
35
35
 
36
+ #include <limits.h>
36
37
  #include <math.h>
37
38
  #include <stdio.h>
38
39
  #include <string.h>
39
40
 
41
+ #include <grpc/slice_buffer.h>
40
42
  #include <grpc/support/alloc.h>
41
43
  #include <grpc/support/log.h>
42
- #include <grpc/support/slice_buffer.h>
43
44
  #include <grpc/support/string_util.h>
44
45
  #include <grpc/support/useful.h>
45
46
 
46
47
  #include "src/core/ext/transport/chttp2/transport/http2_errors.h"
47
48
  #include "src/core/ext/transport/chttp2/transport/internal.h"
48
49
  #include "src/core/ext/transport/chttp2/transport/status_conversion.h"
49
- #include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
50
+ #include "src/core/ext/transport/chttp2/transport/varint.h"
51
+ #include "src/core/lib/channel/channel_args.h"
50
52
  #include "src/core/lib/http/parser.h"
51
53
  #include "src/core/lib/iomgr/workqueue.h"
52
54
  #include "src/core/lib/profiling/timers.h"
55
+ #include "src/core/lib/slice/slice_internal.h"
56
+ #include "src/core/lib/slice/slice_string_helpers.h"
53
57
  #include "src/core/lib/support/string.h"
54
58
  #include "src/core/lib/transport/static_metadata.h"
59
+ #include "src/core/lib/transport/timeout_encoding.h"
55
60
  #include "src/core/lib/transport/transport_impl.h"
56
61
 
57
62
  #define DEFAULT_WINDOW 65535
58
63
  #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
59
64
  #define MAX_WINDOW 0x7fffffffu
60
-
65
+ #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
61
66
  #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
62
67
 
63
68
  #define MAX_CLIENT_STREAM_ID 0x7fffffffu
64
69
  int grpc_http_trace = 0;
65
70
  int grpc_flowctl_trace = 0;
66
- int grpc_http_write_state_trace = 0;
67
-
68
- #define TRANSPORT_FROM_WRITING(tw) \
69
- ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
70
- writing)))
71
-
72
- #define TRANSPORT_FROM_PARSING(tp) \
73
- ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
74
- parsing)))
75
-
76
- #define TRANSPORT_FROM_GLOBAL(tg) \
77
- ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
78
- global)))
79
-
80
- #define STREAM_FROM_GLOBAL(sg) \
81
- ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
82
-
83
- #define STREAM_FROM_PARSING(sg) \
84
- ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, parsing)))
85
71
 
86
72
  static const grpc_transport_vtable vtable;
87
73
 
88
74
  /* forward declarations of various callbacks that we'll build closures around */
89
- static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
90
- static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
91
- static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
92
- static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t,
93
- grpc_error *error);
75
+ static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *t,
76
+ grpc_error *error);
77
+ static void write_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
78
+ static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *t,
79
+ grpc_error *error);
94
80
 
95
- static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
96
- static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
97
- grpc_chttp2_transport *t, grpc_error *error);
81
+ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *t,
82
+ grpc_error *error);
98
83
 
84
+ static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
85
+ grpc_error *error);
99
86
  /** Set a transport level setting, and push it to our peer */
100
87
  static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
101
88
  grpc_chttp2_setting_id id, uint32_t value);
102
89
 
103
- /** Start disconnection chain */
104
- static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
105
- grpc_error *error);
106
-
107
- /** Perform a transport_op */
108
- static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
109
- grpc_chttp2_transport *t,
110
- grpc_chttp2_stream *s, void *transport_op);
111
-
112
- /** Cancel a stream: coming from the transport API */
113
- static void cancel_from_api(grpc_exec_ctx *exec_ctx,
114
- grpc_chttp2_transport_global *transport_global,
115
- grpc_chttp2_stream_global *stream_global,
116
- grpc_error *error);
117
-
118
- static void close_from_api(grpc_exec_ctx *exec_ctx,
119
- grpc_chttp2_transport_global *transport_global,
120
- grpc_chttp2_stream_global *stream_global,
121
- grpc_error *error);
122
-
123
- /** Add endpoint from this transport to pollset */
124
- static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
125
- grpc_chttp2_transport *t,
126
- grpc_chttp2_stream *s_ignored, void *pollset);
127
- static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
128
- grpc_chttp2_transport *t,
129
- grpc_chttp2_stream *s_ignored,
130
- void *pollset_set);
90
+ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
91
+ grpc_chttp2_stream *s, grpc_error *error);
131
92
 
132
93
  /** Start new streams that have been created if we can */
133
- static void maybe_start_some_streams(
134
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global);
94
+ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
95
+ grpc_chttp2_transport *t);
135
96
 
136
- static void finish_global_actions(grpc_exec_ctx *exec_ctx,
137
- grpc_chttp2_transport *t);
97
+ static void connectivity_state_set(grpc_exec_ctx *exec_ctx,
98
+ grpc_chttp2_transport *t,
99
+ grpc_connectivity_state state,
100
+ grpc_error *error, const char *reason);
101
+
102
+ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
103
+ grpc_chttp2_transport *t,
104
+ grpc_chttp2_stream *s,
105
+ size_t max_size_hint,
106
+ size_t have_already);
107
+ static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
108
+ void *byte_stream,
109
+ grpc_error *error_ignored);
138
110
 
139
- static void connectivity_state_set(
140
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
141
- grpc_connectivity_state state, grpc_error *error, const char *reason);
111
+ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *t,
112
+ grpc_error *error);
113
+ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *t,
114
+ grpc_error *error);
142
115
 
143
- static void check_read_ops(grpc_exec_ctx *exec_ctx,
144
- grpc_chttp2_transport_global *transport_global);
116
+ static void post_benign_reclaimer(grpc_exec_ctx *exec_ctx,
117
+ grpc_chttp2_transport *t);
118
+ static void post_destructive_reclaimer(grpc_exec_ctx *exec_ctx,
119
+ grpc_chttp2_transport *t);
145
120
 
146
- static void incoming_byte_stream_update_flow_control(
147
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
148
- grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
149
- size_t have_already);
150
- static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
151
- grpc_chttp2_transport *t,
152
- grpc_chttp2_stream *s,
153
- void *byte_stream);
154
- static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
155
- grpc_chttp2_transport_global *transport_global,
156
- grpc_chttp2_stream_global *stream_global,
157
- grpc_error *error);
121
+ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
122
+ grpc_chttp2_transport *t, grpc_error *error);
123
+ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
124
+ grpc_error *error);
158
125
 
159
126
  /*******************************************************************************
160
127
  * CONSTRUCTION/DESTRUCTION/REFCOUNTING
@@ -164,77 +131,74 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
164
131
  grpc_chttp2_transport *t) {
165
132
  size_t i;
166
133
 
167
- gpr_mu_lock(&t->executor.mu);
168
-
169
- GPR_ASSERT(t->ep == NULL);
134
+ grpc_endpoint_destroy(exec_ctx, t->ep);
170
135
 
171
- gpr_slice_buffer_destroy(&t->global.qbuf);
136
+ grpc_slice_buffer_destroy_internal(exec_ctx, &t->qbuf);
172
137
 
173
- gpr_slice_buffer_destroy(&t->writing.outbuf);
174
- grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor);
138
+ grpc_slice_buffer_destroy_internal(exec_ctx, &t->outbuf);
139
+ grpc_chttp2_hpack_compressor_destroy(exec_ctx, &t->hpack_compressor);
175
140
 
176
- gpr_slice_buffer_destroy(&t->parsing.qbuf);
177
- gpr_slice_buffer_destroy(&t->read_buffer);
178
- grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser);
179
- grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser);
141
+ grpc_slice_buffer_destroy_internal(exec_ctx, &t->read_buffer);
142
+ grpc_chttp2_hpack_parser_destroy(exec_ctx, &t->hpack_parser);
143
+ grpc_chttp2_goaway_parser_destroy(&t->goaway_parser);
180
144
 
181
145
  for (i = 0; i < STREAM_LIST_COUNT; i++) {
182
146
  GPR_ASSERT(t->lists[i].head == NULL);
183
147
  GPR_ASSERT(t->lists[i].tail == NULL);
184
148
  }
185
149
 
186
- GPR_ASSERT(grpc_chttp2_stream_map_size(&t->parsing_stream_map) == 0);
187
- GPR_ASSERT(grpc_chttp2_stream_map_size(&t->new_stream_map) == 0);
150
+ GPR_ASSERT(grpc_chttp2_stream_map_size(&t->stream_map) == 0);
188
151
 
189
- grpc_chttp2_stream_map_destroy(&t->parsing_stream_map);
190
- grpc_chttp2_stream_map_destroy(&t->new_stream_map);
152
+ grpc_chttp2_stream_map_destroy(&t->stream_map);
191
153
  grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
192
154
 
193
- gpr_mu_unlock(&t->executor.mu);
194
- gpr_mu_destroy(&t->executor.mu);
155
+ grpc_combiner_destroy(exec_ctx, t->combiner);
195
156
 
196
157
  /* callback remaining pings: they're not allowed to call into the transpot,
197
158
  and maybe they hold resources that need to be freed */
198
- while (t->global.pings.next != &t->global.pings) {
199
- grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
200
- grpc_exec_ctx_sched(exec_ctx, ping->on_recv,
201
- GRPC_ERROR_CREATE("Transport closed"), NULL);
159
+ while (t->pings.next != &t->pings) {
160
+ grpc_chttp2_outstanding_ping *ping = t->pings.next;
161
+ grpc_closure_sched(exec_ctx, ping->on_recv,
162
+ GRPC_ERROR_CREATE("Transport closed"));
202
163
  ping->next->prev = ping->prev;
203
164
  ping->prev->next = ping->next;
204
165
  gpr_free(ping);
205
166
  }
206
167
 
168
+ while (t->write_cb_pool) {
169
+ grpc_chttp2_write_cb *next = t->write_cb_pool->next;
170
+ gpr_free(t->write_cb_pool);
171
+ t->write_cb_pool = next;
172
+ }
173
+
207
174
  gpr_free(t->peer_string);
208
175
  gpr_free(t);
209
176
  }
210
177
 
211
- /*#define REFCOUNTING_DEBUG 1*/
212
- #ifdef REFCOUNTING_DEBUG
213
- #define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__)
214
- #define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t, r, __FILE__, __LINE__)
215
- static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
216
- const char *reason, const char *file, int line) {
217
- gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count,
218
- t->refs.count - 1, reason, file, line);
178
+ #ifdef GRPC_CHTTP2_REFCOUNTING_DEBUG
179
+ void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx,
180
+ grpc_chttp2_transport *t, const char *reason,
181
+ const char *file, int line) {
182
+ gpr_log(GPR_DEBUG, "chttp2:unref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", t,
183
+ t->refs.count, t->refs.count - 1, reason, file, line);
219
184
  if (!gpr_unref(&t->refs)) return;
220
185
  destruct_transport(exec_ctx, t);
221
186
  }
222
187
 
223
- static void ref_transport(grpc_chttp2_transport *t, const char *reason,
224
- const char *file, int line) {
225
- gpr_log(GPR_DEBUG, "chttp2: ref:%p %d->%d %s [%s:%d]", t, t->refs.count,
226
- t->refs.count + 1, reason, file, line);
188
+ void grpc_chttp2_ref_transport(grpc_chttp2_transport *t, const char *reason,
189
+ const char *file, int line) {
190
+ gpr_log(GPR_DEBUG, "chttp2: ref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", t,
191
+ t->refs.count, t->refs.count + 1, reason, file, line);
227
192
  gpr_ref(&t->refs);
228
193
  }
229
194
  #else
230
- #define REF_TRANSPORT(t, r) ref_transport(t)
231
- #define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t)
232
- static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
195
+ void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx,
196
+ grpc_chttp2_transport *t) {
233
197
  if (!gpr_unref(&t->refs)) return;
234
198
  destruct_transport(exec_ctx, t);
235
199
  }
236
200
 
237
- static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
201
+ void grpc_chttp2_ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
238
202
  #endif
239
203
 
240
204
  static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@@ -250,74 +214,70 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
250
214
 
251
215
  t->base.vtable = &vtable;
252
216
  t->ep = ep;
253
- /* one ref is for destroy, the other for when ep becomes NULL */
254
- gpr_ref_init(&t->refs, 2);
255
- /* ref is dropped at transport close() */
256
- gpr_ref_init(&t->shutdown_ep_refs, 1);
257
- gpr_mu_init(&t->executor.mu);
217
+ /* one ref is for destroy */
218
+ gpr_ref_init(&t->refs, 1);
219
+ t->combiner = grpc_combiner_create(grpc_endpoint_get_workqueue(ep));
258
220
  t->peer_string = grpc_endpoint_get_peer(ep);
259
221
  t->endpoint_reading = 1;
260
- t->global.next_stream_id = is_client ? 1 : 2;
261
- t->global.is_client = is_client;
262
- t->writing.outgoing_window = DEFAULT_WINDOW;
263
- t->parsing.incoming_window = DEFAULT_WINDOW;
264
- t->global.stream_lookahead = DEFAULT_WINDOW;
265
- t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
266
- t->global.ping_counter = 1;
267
- t->global.pings.next = t->global.pings.prev = &t->global.pings;
268
- t->parsing.is_client = is_client;
269
- t->parsing.deframe_state =
270
- is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
271
- t->parsing.is_first_frame = true;
272
- t->writing.is_client = is_client;
222
+ t->next_stream_id = is_client ? 1 : 2;
223
+ t->is_client = is_client;
224
+ t->outgoing_window = DEFAULT_WINDOW;
225
+ t->incoming_window = DEFAULT_WINDOW;
226
+ t->stream_lookahead = DEFAULT_WINDOW;
227
+ t->connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
228
+ t->ping_counter = 1;
229
+ t->pings.next = t->pings.prev = &t->pings;
230
+ t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
231
+ t->is_first_frame = true;
273
232
  grpc_connectivity_state_init(
274
233
  &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
275
234
  is_client ? "client_transport" : "server_transport");
276
235
 
277
- gpr_slice_buffer_init(&t->global.qbuf);
236
+ grpc_slice_buffer_init(&t->qbuf);
278
237
 
279
- gpr_slice_buffer_init(&t->writing.outbuf);
280
- grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor);
281
- grpc_closure_init(&t->writing_action, writing_action, t);
282
- grpc_closure_init(&t->reading_action, reading_action, t);
283
- grpc_closure_init(&t->parsing_action, parsing_action, t);
284
- grpc_closure_init(&t->initiate_writing, initiate_writing, t);
238
+ grpc_slice_buffer_init(&t->outbuf);
239
+ grpc_chttp2_hpack_compressor_init(&t->hpack_compressor);
285
240
 
286
- gpr_slice_buffer_init(&t->parsing.qbuf);
287
- grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser);
288
- grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser);
241
+ grpc_closure_init(&t->write_action, write_action, t,
242
+ grpc_schedule_on_exec_ctx);
243
+ grpc_closure_init(&t->read_action_locked, read_action_locked, t,
244
+ grpc_combiner_scheduler(t->combiner, false));
245
+ grpc_closure_init(&t->benign_reclaimer_locked, benign_reclaimer_locked, t,
246
+ grpc_combiner_scheduler(t->combiner, false));
247
+ grpc_closure_init(&t->destructive_reclaimer_locked,
248
+ destructive_reclaimer_locked, t,
249
+ grpc_combiner_scheduler(t->combiner, false));
289
250
 
290
- grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing,
291
- &t->writing);
292
- gpr_slice_buffer_init(&t->read_buffer);
251
+ grpc_chttp2_goaway_parser_init(&t->goaway_parser);
252
+ grpc_chttp2_hpack_parser_init(exec_ctx, &t->hpack_parser);
253
+
254
+ grpc_slice_buffer_init(&t->read_buffer);
293
255
 
294
- if (is_client) {
295
- gpr_slice_buffer_add(
296
- &t->global.qbuf,
297
- gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
298
- grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write");
299
- }
300
256
  /* 8 is a random stab in the dark as to a good initial size: it's small enough
301
257
  that it shouldn't waste memory for infrequently used connections, yet
302
258
  large enough that the exponential growth should happen nicely when it's
303
259
  needed.
304
260
  TODO(ctiller): tune this */
305
- grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8);
306
- grpc_chttp2_stream_map_init(&t->new_stream_map, 8);
261
+ grpc_chttp2_stream_map_init(&t->stream_map, 8);
307
262
 
308
263
  /* copy in initial settings to all setting sets */
309
264
  for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) {
310
- t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value;
311
265
  for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) {
312
- t->global.settings[j][i] =
313
- grpc_chttp2_settings_parameters[i].default_value;
266
+ t->settings[j][i] = grpc_chttp2_settings_parameters[i].default_value;
314
267
  }
315
268
  }
316
- t->global.dirtied_local_settings = 1;
269
+ t->dirtied_local_settings = 1;
317
270
  /* Hack: it's common for implementations to assume 65536 bytes initial send
318
271
  window -- this should by rights be 0 */
319
- t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
320
- t->global.sent_local_settings = 0;
272
+ t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
273
+ t->sent_local_settings = 0;
274
+ t->write_buffer_size = DEFAULT_WINDOW;
275
+
276
+ if (is_client) {
277
+ grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string(
278
+ GRPC_CHTTP2_CLIENT_CONNECT_STRING));
279
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "initial_write");
280
+ }
321
281
 
322
282
  /* configure http2 the way we like it */
323
283
  if (is_client) {
@@ -331,681 +291,483 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
331
291
 
332
292
  if (channel_args) {
333
293
  for (i = 0; i < channel_args->num_args; i++) {
334
- if (0 ==
335
- strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) {
336
- if (is_client) {
337
- gpr_log(GPR_ERROR, "%s: is ignored on the client",
338
- GRPC_ARG_MAX_CONCURRENT_STREAMS);
339
- } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
340
- gpr_log(GPR_ERROR, "%s: must be an integer",
341
- GRPC_ARG_MAX_CONCURRENT_STREAMS);
342
- } else {
343
- push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
344
- (uint32_t)channel_args->args[i].value.integer);
345
- }
346
- } else if (0 == strcmp(channel_args->args[i].key,
347
- GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
348
- if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
349
- gpr_log(GPR_ERROR, "%s: must be an integer",
350
- GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER);
351
- } else if ((t->global.next_stream_id & 1) !=
352
- (channel_args->args[i].value.integer & 1)) {
353
- gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
354
- GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER,
355
- t->global.next_stream_id & 1,
356
- is_client ? "client" : "server");
357
- } else {
358
- t->global.next_stream_id =
359
- (uint32_t)channel_args->args[i].value.integer;
294
+ if (0 == strcmp(channel_args->args[i].key,
295
+ GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
296
+ const grpc_integer_options options = {-1, 0, INT_MAX};
297
+ const int value =
298
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
299
+ if (value >= 0) {
300
+ if ((t->next_stream_id & 1) != (value & 1)) {
301
+ gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
302
+ GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER,
303
+ t->next_stream_id & 1, is_client ? "client" : "server");
304
+ } else {
305
+ t->next_stream_id = (uint32_t)value;
306
+ }
360
307
  }
361
308
  } else if (0 == strcmp(channel_args->args[i].key,
362
309
  GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
363
- if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
364
- gpr_log(GPR_ERROR, "%s: must be an integer",
365
- GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
366
- } else if (channel_args->args[i].value.integer <= 5) {
367
- gpr_log(GPR_ERROR, "%s: must be at least 5",
368
- GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
369
- } else {
370
- t->global.stream_lookahead =
371
- (uint32_t)channel_args->args[i].value.integer;
372
- }
373
- } else if (0 == strcmp(channel_args->args[i].key,
374
- GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) {
375
- if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
376
- gpr_log(GPR_ERROR, "%s: must be an integer",
377
- GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
378
- } else if (channel_args->args[i].value.integer < 0) {
379
- gpr_log(GPR_ERROR, "%s: must be non-negative",
380
- GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
381
- } else {
382
- push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
383
- (uint32_t)channel_args->args[i].value.integer);
310
+ const grpc_integer_options options = {-1, 5, INT_MAX};
311
+ const int value =
312
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
313
+ if (value >= 0) {
314
+ t->stream_lookahead = (uint32_t)value;
384
315
  }
385
316
  } else if (0 == strcmp(channel_args->args[i].key,
386
317
  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
387
- if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
388
- gpr_log(GPR_ERROR, "%s: must be an integer",
389
- GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
390
- } else if (channel_args->args[i].value.integer < 0) {
391
- gpr_log(GPR_ERROR, "%s: must be non-negative",
392
- GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
393
- } else {
394
- grpc_chttp2_hpack_compressor_set_max_usable_size(
395
- &t->writing.hpack_compressor,
396
- (uint32_t)channel_args->args[i].value.integer);
318
+ const grpc_integer_options options = {-1, 0, INT_MAX};
319
+ const int value =
320
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
321
+ if (value >= 0) {
322
+ grpc_chttp2_hpack_compressor_set_max_usable_size(&t->hpack_compressor,
323
+ (uint32_t)value);
397
324
  }
398
325
  } else if (0 == strcmp(channel_args->args[i].key,
399
- GRPC_ARG_MAX_METADATA_SIZE)) {
400
- if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
401
- gpr_log(GPR_ERROR, "%s: must be an integer",
402
- GRPC_ARG_MAX_METADATA_SIZE);
403
- } else if (channel_args->args[i].value.integer < 0) {
404
- gpr_log(GPR_ERROR, "%s: must be non-negative",
405
- GRPC_ARG_MAX_METADATA_SIZE);
406
- } else {
407
- push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
408
- (uint32_t)channel_args->args[i].value.integer);
326
+ GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) {
327
+ t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
328
+ &channel_args->args[i],
329
+ (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE});
330
+ } else {
331
+ static const struct {
332
+ const char *channel_arg_name;
333
+ grpc_chttp2_setting_id setting_id;
334
+ grpc_integer_options integer_options;
335
+ bool availability[2] /* server, client */;
336
+ } settings_map[] = {
337
+ {GRPC_ARG_MAX_CONCURRENT_STREAMS,
338
+ GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
339
+ {-1, 0, INT_MAX},
340
+ {true, false}},
341
+ {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
342
+ GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
343
+ {-1, 0, INT_MAX},
344
+ {true, true}},
345
+ {GRPC_ARG_MAX_METADATA_SIZE,
346
+ GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
347
+ {-1, 0, INT_MAX},
348
+ {true, true}},
349
+ {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
350
+ GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
351
+ {-1, 16384, 16777215},
352
+ {true, true}},
353
+ };
354
+ for (j = 0; j < (int)GPR_ARRAY_SIZE(settings_map); j++) {
355
+ if (0 == strcmp(channel_args->args[i].key,
356
+ settings_map[j].channel_arg_name)) {
357
+ if (!settings_map[j].availability[is_client]) {
358
+ gpr_log(GPR_DEBUG, "%s is not available on %s",
359
+ settings_map[j].channel_arg_name,
360
+ is_client ? "clients" : "servers");
361
+ } else {
362
+ int value = grpc_channel_arg_get_integer(
363
+ &channel_args->args[i], settings_map[j].integer_options);
364
+ if (value >= 0) {
365
+ push_setting(exec_ctx, t, settings_map[j].setting_id,
366
+ (uint32_t)value);
367
+ }
368
+ }
369
+ break;
370
+ }
409
371
  }
410
372
  }
411
373
  }
412
374
  }
375
+
376
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "init");
377
+ post_benign_reclaimer(exec_ctx, t);
413
378
  }
414
379
 
415
- static void destroy_transport_locked(grpc_exec_ctx *exec_ctx,
416
- grpc_chttp2_transport *t,
417
- grpc_chttp2_stream *s_ignored,
418
- void *arg_ignored) {
380
+ static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, void *tp,
381
+ grpc_error *error) {
382
+ grpc_chttp2_transport *t = tp;
419
383
  t->destroying = 1;
420
- drop_connection(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
384
+ close_transport_locked(
385
+ exec_ctx, t,
386
+ grpc_error_set_int(GRPC_ERROR_CREATE("Transport destroyed"),
387
+ GRPC_ERROR_INT_OCCURRED_DURING_WRITE, t->write_state));
388
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "destroy");
421
389
  }
422
390
 
423
391
  static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
424
392
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
425
- grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, destroy_transport_locked,
426
- NULL, 0);
427
- UNREF_TRANSPORT(exec_ctx, t, "destroy");
428
- }
429
-
430
- /** block grpc_endpoint_shutdown being called until a paired
431
- allow_endpoint_shutdown is made */
432
- static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) {
433
- GPR_ASSERT(t->ep);
434
- gpr_ref(&t->shutdown_ep_refs);
435
- }
436
-
437
- static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx,
438
- grpc_chttp2_transport *t) {
439
- if (gpr_unref(&t->shutdown_ep_refs)) {
440
- if (t->ep) {
441
- grpc_endpoint_shutdown(exec_ctx, t->ep);
442
- }
443
- }
444
- }
445
-
446
- static void destroy_endpoint(grpc_exec_ctx *exec_ctx,
447
- grpc_chttp2_transport *t) {
448
- grpc_endpoint_destroy(exec_ctx, t->ep);
449
- t->ep = NULL;
450
- /* safe because we'll still have the ref for write */
451
- UNREF_TRANSPORT(exec_ctx, t, "disconnect");
393
+ grpc_closure_sched(exec_ctx, grpc_closure_create(
394
+ destroy_transport_locked, t,
395
+ grpc_combiner_scheduler(t->combiner, false)),
396
+ GRPC_ERROR_NONE);
452
397
  }
453
398
 
454
399
  static void close_transport_locked(grpc_exec_ctx *exec_ctx,
455
400
  grpc_chttp2_transport *t,
456
401
  grpc_error *error) {
457
402
  if (!t->closed) {
458
- if (grpc_http_write_state_trace) {
459
- gpr_log(GPR_DEBUG, "W:%p close transport", t);
403
+ if (t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE) {
404
+ if (t->close_transport_on_writes_finished == NULL) {
405
+ t->close_transport_on_writes_finished =
406
+ GRPC_ERROR_CREATE("Delayed close due to in-progress write");
407
+ }
408
+ t->close_transport_on_writes_finished =
409
+ grpc_error_add_child(t->close_transport_on_writes_finished, error);
410
+ return;
411
+ }
412
+ if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) {
413
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
414
+ GRPC_STATUS_UNAVAILABLE);
460
415
  }
461
416
  t->closed = 1;
462
- connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN,
417
+ connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
463
418
  GRPC_ERROR_REF(error), "close_transport");
464
- if (t->ep) {
465
- allow_endpoint_shutdown_locked(exec_ctx, t);
466
- }
419
+ grpc_endpoint_shutdown(exec_ctx, t->ep);
467
420
 
468
421
  /* flush writable stream list to avoid dangling references */
469
- grpc_chttp2_stream_global *stream_global;
470
- grpc_chttp2_stream_writing *stream_writing;
471
- while (grpc_chttp2_list_pop_writable_stream(
472
- &t->global, &t->writing, &stream_global, &stream_writing)) {
473
- GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
422
+ grpc_chttp2_stream *s;
423
+ while (grpc_chttp2_list_pop_writable_stream(t, &s)) {
424
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:close");
474
425
  }
426
+ end_all_the_calls(exec_ctx, t, GRPC_ERROR_REF(error));
475
427
  }
476
428
  GRPC_ERROR_UNREF(error);
477
429
  }
478
430
 
479
431
  #ifdef GRPC_STREAM_REFCOUNT_DEBUG
480
- void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global,
481
- const char *reason) {
482
- grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount, reason);
432
+ void grpc_chttp2_stream_ref(grpc_chttp2_stream *s, const char *reason) {
433
+ grpc_stream_ref(s->refcount, reason);
483
434
  }
484
- void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
485
- grpc_chttp2_stream_global *stream_global,
435
+ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s,
486
436
  const char *reason) {
487
- grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount,
488
- reason);
437
+ grpc_stream_unref(exec_ctx, s->refcount, reason);
489
438
  }
490
439
  #else
491
- void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global) {
492
- grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount);
440
+ void grpc_chttp2_stream_ref(grpc_chttp2_stream *s) {
441
+ grpc_stream_ref(s->refcount);
493
442
  }
494
- void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
495
- grpc_chttp2_stream_global *stream_global) {
496
- grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount);
443
+ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s) {
444
+ grpc_stream_unref(exec_ctx, s->refcount);
497
445
  }
498
446
  #endif
499
447
 
500
- static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx,
501
- grpc_chttp2_transport *t,
502
- grpc_chttp2_stream *s,
503
- void *arg_ignored) {
504
- grpc_chttp2_register_stream(t, s);
505
- }
506
-
507
448
  static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
508
449
  grpc_stream *gs, grpc_stream_refcount *refcount,
509
450
  const void *server_data) {
451
+ GPR_TIMER_BEGIN("init_stream", 0);
510
452
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
511
453
  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
512
454
 
513
455
  memset(s, 0, sizeof(*s));
514
456
 
457
+ s->t = t;
515
458
  s->refcount = refcount;
516
459
  /* We reserve one 'active stream' that's dropped when the stream is
517
460
  read-closed. The others are for incoming_byte_streams that are actively
518
461
  reading */
519
- gpr_ref_init(&s->global.active_streams, 1);
520
- GRPC_CHTTP2_STREAM_REF(&s->global, "chttp2");
462
+ gpr_ref_init(&s->active_streams, 1);
463
+ GRPC_CHTTP2_STREAM_REF(s, "chttp2");
521
464
 
522
- grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[0]);
523
- grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[1]);
524
- grpc_chttp2_incoming_metadata_buffer_init(
525
- &s->global.received_initial_metadata);
526
- grpc_chttp2_incoming_metadata_buffer_init(
527
- &s->global.received_trailing_metadata);
528
- grpc_chttp2_data_parser_init(&s->parsing.data_parser);
529
- gpr_slice_buffer_init(&s->writing.flow_controlled_buffer);
530
- s->global.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
465
+ grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0]);
466
+ grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1]);
467
+ grpc_chttp2_data_parser_init(&s->data_parser);
468
+ grpc_slice_buffer_init(&s->flow_controlled_buffer);
469
+ s->deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
470
+ grpc_closure_init(&s->complete_fetch_locked, complete_fetch_locked, s,
471
+ grpc_schedule_on_exec_ctx);
531
472
 
532
- REF_TRANSPORT(t, "stream");
473
+ GRPC_CHTTP2_REF_TRANSPORT(t, "stream");
533
474
 
534
475
  if (server_data) {
535
- GPR_ASSERT(t->executor.parsing_active);
536
- s->global.id = (uint32_t)(uintptr_t)server_data;
537
- s->parsing.id = s->global.id;
538
- s->global.outgoing_window =
539
- t->global.settings[GRPC_PEER_SETTINGS]
540
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
541
- s->parsing.incoming_window = s->global.max_recv_bytes =
542
- t->global.settings[GRPC_SENT_SETTINGS]
543
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
476
+ s->id = (uint32_t)(uintptr_t)server_data;
477
+ s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
478
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
479
+ s->incoming_window = s->max_recv_bytes =
480
+ t->settings[GRPC_SENT_SETTINGS]
481
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
544
482
  *t->accepting_stream = s;
545
- grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s);
546
- s->global.in_stream_map = true;
483
+ grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
484
+ post_destructive_reclaimer(exec_ctx, t);
547
485
  }
548
486
 
549
- grpc_chttp2_run_with_global_lock(exec_ctx, t, s, finish_init_stream_locked,
550
- NULL, 0);
487
+ GPR_TIMER_END("init_stream", 0);
551
488
 
552
489
  return 0;
553
490
  }
554
491
 
555
- static void destroy_stream_locked(grpc_exec_ctx *exec_ctx,
556
- grpc_chttp2_transport *t,
557
- grpc_chttp2_stream *s, void *arg) {
492
+ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
493
+ grpc_error *error) {
558
494
  grpc_byte_stream *bs;
495
+ grpc_chttp2_stream *s = sp;
496
+ grpc_chttp2_transport *t = s->t;
559
497
 
560
498
  GPR_TIMER_BEGIN("destroy_stream", 0);
561
499
 
562
- GPR_ASSERT((s->global.write_closed && s->global.read_closed) ||
563
- s->global.id == 0);
564
- GPR_ASSERT(!s->global.in_stream_map);
565
- if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
566
- close_transport_locked(
567
- exec_ctx, t,
568
- GRPC_ERROR_CREATE("Last stream closed after sending goaway"));
569
- }
570
- if (!t->executor.parsing_active && s->global.id) {
571
- GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
572
- s->global.id) == NULL);
500
+ GPR_ASSERT((s->write_closed && s->read_closed) || s->id == 0);
501
+ if (s->id != 0) {
502
+ GPR_ASSERT(grpc_chttp2_stream_map_find(&t->stream_map, s->id) == NULL);
573
503
  }
574
504
 
575
- while (
576
- (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) {
577
- incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
505
+ while ((bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames))) {
506
+ incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE);
578
507
  }
579
508
 
580
- grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global,
581
- &s->global);
582
- grpc_chttp2_list_remove_stalled_by_transport(&t->global, &s->global);
583
- grpc_chttp2_list_remove_check_read_ops(&t->global, &s->global);
509
+ grpc_chttp2_list_remove_stalled_by_transport(t, s);
584
510
 
585
511
  for (int i = 0; i < STREAM_LIST_COUNT; i++) {
586
512
  if (s->included[i]) {
587
513
  gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
588
- t->global.is_client ? "client" : "server", s->global.id, i);
514
+ t->is_client ? "client" : "server", s->id, i);
589
515
  abort();
590
516
  }
591
517
  }
592
518
 
593
- GPR_ASSERT(s->global.send_initial_metadata_finished == NULL);
594
- GPR_ASSERT(s->global.send_message_finished == NULL);
595
- GPR_ASSERT(s->global.send_trailing_metadata_finished == NULL);
596
- GPR_ASSERT(s->global.recv_initial_metadata_ready == NULL);
597
- GPR_ASSERT(s->global.recv_message_ready == NULL);
598
- GPR_ASSERT(s->global.recv_trailing_metadata_finished == NULL);
599
- grpc_chttp2_data_parser_destroy(exec_ctx, &s->parsing.data_parser);
600
- grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[0]);
601
- grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[1]);
602
- grpc_chttp2_incoming_metadata_buffer_destroy(
603
- &s->global.received_initial_metadata);
604
- grpc_chttp2_incoming_metadata_buffer_destroy(
605
- &s->global.received_trailing_metadata);
606
- gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer);
607
- GRPC_ERROR_UNREF(s->global.read_closed_error);
608
- GRPC_ERROR_UNREF(s->global.write_closed_error);
609
-
610
- UNREF_TRANSPORT(exec_ctx, t, "stream");
519
+ GPR_ASSERT(s->send_initial_metadata_finished == NULL);
520
+ GPR_ASSERT(s->fetching_send_message == NULL);
521
+ GPR_ASSERT(s->send_trailing_metadata_finished == NULL);
522
+ GPR_ASSERT(s->recv_initial_metadata_ready == NULL);
523
+ GPR_ASSERT(s->recv_message_ready == NULL);
524
+ GPR_ASSERT(s->recv_trailing_metadata_finished == NULL);
525
+ grpc_chttp2_data_parser_destroy(exec_ctx, &s->data_parser);
526
+ grpc_chttp2_incoming_metadata_buffer_destroy(exec_ctx,
527
+ &s->metadata_buffer[0]);
528
+ grpc_chttp2_incoming_metadata_buffer_destroy(exec_ctx,
529
+ &s->metadata_buffer[1]);
530
+ grpc_slice_buffer_destroy_internal(exec_ctx, &s->flow_controlled_buffer);
531
+ GRPC_ERROR_UNREF(s->read_closed_error);
532
+ GRPC_ERROR_UNREF(s->write_closed_error);
533
+
534
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
611
535
 
612
536
  GPR_TIMER_END("destroy_stream", 0);
613
537
 
614
- gpr_free(arg);
538
+ gpr_free(s->destroy_stream_arg);
615
539
  }
616
540
 
617
541
  static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
618
542
  grpc_stream *gs, void *and_free_memory) {
543
+ GPR_TIMER_BEGIN("destroy_stream", 0);
619
544
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
620
545
  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
621
546
 
622
- grpc_chttp2_run_with_global_lock(exec_ctx, t, s, destroy_stream_locked,
623
- and_free_memory, 0);
547
+ s->destroy_stream_arg = and_free_memory;
548
+ grpc_closure_sched(
549
+ exec_ctx, grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s,
550
+ grpc_combiner_scheduler(t->combiner, false)),
551
+ GRPC_ERROR_NONE);
552
+ GPR_TIMER_END("destroy_stream", 0);
624
553
  }
625
554
 
626
- grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
627
- grpc_chttp2_transport_parsing *transport_parsing, uint32_t id) {
628
- grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
629
- grpc_chttp2_stream *s =
630
- grpc_chttp2_stream_map_find(&t->parsing_stream_map, id);
631
- return s ? &s->parsing : NULL;
555
+ grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t,
556
+ uint32_t id) {
557
+ return grpc_chttp2_stream_map_find(&t->stream_map, id);
632
558
  }
633
559
 
634
- grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
635
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
636
- uint32_t id) {
560
+ grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx,
561
+ grpc_chttp2_transport *t,
562
+ uint32_t id) {
563
+ if (t->channel_callback.accept_stream == NULL) {
564
+ return NULL;
565
+ }
637
566
  grpc_chttp2_stream *accepting;
638
- grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
639
567
  GPR_ASSERT(t->accepting_stream == NULL);
640
568
  t->accepting_stream = &accepting;
641
569
  t->channel_callback.accept_stream(exec_ctx,
642
570
  t->channel_callback.accept_stream_user_data,
643
571
  &t->base, (void *)(uintptr_t)id);
644
572
  t->accepting_stream = NULL;
645
- return &accepting->parsing;
573
+ return accepting;
646
574
  }
647
575
 
648
576
  /*******************************************************************************
649
- * LOCK MANAGEMENT
577
+ * OUTPUT PROCESSING
650
578
  */
651
579
 
652
- static const char *write_state_name(grpc_chttp2_write_state state) {
653
- switch (state) {
654
- case GRPC_CHTTP2_WRITING_INACTIVE:
655
- return "INACTIVE";
656
- case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
657
- return "REQUESTED[p=0]";
658
- case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
659
- return "REQUESTED[p=1]";
660
- case GRPC_CHTTP2_WRITE_SCHEDULED:
661
- return "SCHEDULED";
662
- case GRPC_CHTTP2_WRITING:
580
+ static const char *write_state_name(grpc_chttp2_write_state st) {
581
+ switch (st) {
582
+ case GRPC_CHTTP2_WRITE_STATE_IDLE:
583
+ return "IDLE";
584
+ case GRPC_CHTTP2_WRITE_STATE_WRITING:
663
585
  return "WRITING";
664
- case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
665
- return "WRITING[p=1]";
666
- case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
667
- return "WRITING[p=0]";
586
+ case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
587
+ return "WRITING+MORE";
588
+ case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER:
589
+ return "WRITING+MORE+COVERED";
668
590
  }
669
591
  GPR_UNREACHABLE_CODE(return "UNKNOWN");
670
592
  }
671
593
 
672
- static void set_write_state(grpc_chttp2_transport *t,
673
- grpc_chttp2_write_state state, const char *reason) {
674
- if (grpc_http_write_state_trace) {
675
- gpr_log(GPR_DEBUG, "W:%p %s -> %s because %s", t,
676
- write_state_name(t->executor.write_state), write_state_name(state),
677
- reason);
678
- }
679
- t->executor.write_state = state;
680
- }
681
-
682
- static void finish_global_actions(grpc_exec_ctx *exec_ctx,
683
- grpc_chttp2_transport *t) {
684
- grpc_chttp2_executor_action_header *hdr;
685
- grpc_chttp2_executor_action_header *next;
686
-
687
- GPR_TIMER_BEGIN("finish_global_actions", 0);
688
-
689
- for (;;) {
690
- check_read_ops(exec_ctx, &t->global);
691
-
692
- gpr_mu_lock(&t->executor.mu);
693
- if (t->executor.pending_actions_head != NULL) {
694
- hdr = t->executor.pending_actions_head;
695
- t->executor.pending_actions_head = t->executor.pending_actions_tail =
696
- NULL;
697
- gpr_mu_unlock(&t->executor.mu);
698
- while (hdr != NULL) {
699
- GPR_TIMER_BEGIN("chttp2:locked_action", 0);
700
- hdr->action(exec_ctx, t, hdr->stream, hdr->arg);
701
- GPR_TIMER_END("chttp2:locked_action", 0);
702
- next = hdr->next;
703
- gpr_free(hdr);
704
- UNREF_TRANSPORT(exec_ctx, t, "pending_action");
705
- hdr = next;
706
- }
707
- continue;
708
- } else {
709
- t->executor.global_active = false;
710
- switch (t->executor.write_state) {
711
- case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
712
- set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "unlocking");
713
- REF_TRANSPORT(t, "initiate_writing");
714
- gpr_mu_unlock(&t->executor.mu);
715
- grpc_exec_ctx_sched(
716
- exec_ctx, &t->initiate_writing, GRPC_ERROR_NONE,
717
- t->ep != NULL ? grpc_endpoint_get_workqueue(t->ep) : NULL);
718
- break;
719
- case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
720
- start_writing(exec_ctx, t);
721
- gpr_mu_unlock(&t->executor.mu);
722
- break;
723
- case GRPC_CHTTP2_WRITING_INACTIVE:
724
- case GRPC_CHTTP2_WRITING:
725
- case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
726
- case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
727
- case GRPC_CHTTP2_WRITE_SCHEDULED:
728
- gpr_mu_unlock(&t->executor.mu);
729
- break;
730
- }
594
+ static void set_write_state(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
595
+ grpc_chttp2_write_state st, const char *reason) {
596
+ GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_DEBUG, "W:%p %s state %s -> %s [%s]", t,
597
+ t->is_client ? "CLIENT" : "SERVER",
598
+ write_state_name(t->write_state),
599
+ write_state_name(st), reason));
600
+ t->write_state = st;
601
+ if (st == GRPC_CHTTP2_WRITE_STATE_IDLE) {
602
+ grpc_closure_list_sched(exec_ctx, &t->run_after_write);
603
+ if (t->close_transport_on_writes_finished != NULL) {
604
+ grpc_error *err = t->close_transport_on_writes_finished;
605
+ t->close_transport_on_writes_finished = NULL;
606
+ close_transport_locked(exec_ctx, t, err);
731
607
  }
732
- break;
733
608
  }
734
-
735
- GPR_TIMER_END("finish_global_actions", 0);
736
- }
737
-
738
- void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
739
- grpc_chttp2_transport *t,
740
- grpc_chttp2_stream *optional_stream,
741
- grpc_chttp2_locked_action action,
742
- void *arg, size_t sizeof_arg) {
743
- grpc_chttp2_executor_action_header *hdr;
744
-
745
- GPR_TIMER_BEGIN("grpc_chttp2_run_with_global_lock", 0);
746
-
747
- REF_TRANSPORT(t, "run_global");
748
- gpr_mu_lock(&t->executor.mu);
749
-
750
- for (;;) {
751
- if (!t->executor.global_active) {
752
- t->executor.global_active = 1;
753
- gpr_mu_unlock(&t->executor.mu);
754
-
755
- GPR_TIMER_BEGIN("chttp2:locked_action", 0);
756
- action(exec_ctx, t, optional_stream, arg);
757
- GPR_TIMER_END("chttp2:locked_action", 0);
758
-
759
- finish_global_actions(exec_ctx, t);
760
- } else {
761
- gpr_mu_unlock(&t->executor.mu);
762
-
763
- hdr = gpr_malloc(sizeof(*hdr) + sizeof_arg);
764
- hdr->stream = optional_stream;
765
- hdr->action = action;
766
- if (sizeof_arg == 0) {
767
- hdr->arg = arg;
768
- } else {
769
- hdr->arg = hdr + 1;
770
- memcpy(hdr->arg, arg, sizeof_arg);
771
- }
772
-
773
- gpr_mu_lock(&t->executor.mu);
774
- if (!t->executor.global_active) {
775
- /* global lock was released while allocating memory: release & retry */
776
- gpr_free(hdr);
777
- continue;
778
- }
779
- hdr->next = NULL;
780
- if (t->executor.pending_actions_head != NULL) {
781
- t->executor.pending_actions_tail =
782
- t->executor.pending_actions_tail->next = hdr;
783
- } else {
784
- t->executor.pending_actions_tail = t->executor.pending_actions_head =
785
- hdr;
786
- }
787
- REF_TRANSPORT(t, "pending_action");
788
- gpr_mu_unlock(&t->executor.mu);
789
- }
790
- break;
791
- }
792
-
793
- UNREF_TRANSPORT(exec_ctx, t, "run_global");
794
-
795
- GPR_TIMER_END("grpc_chttp2_run_with_global_lock", 0);
796
609
  }
797
610
 
798
- /*******************************************************************************
799
- * OUTPUT PROCESSING
800
- */
801
-
802
611
  void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
803
- grpc_chttp2_transport_global *transport_global,
612
+ grpc_chttp2_transport *t,
804
613
  bool covered_by_poller, const char *reason) {
805
- /* Perform state checks, and transition to a scheduled state if appropriate.
806
- Each time we finish the global lock execution, we check if we need to
807
- write. If we do:
808
- - (if there is a poller surrounding the write) schedule
809
- initiate_writing, which locks and calls initiate_writing_locked to...
810
- - call start_writing, which verifies (under the global lock) that there
811
- are things that need to be written by calling
812
- grpc_chttp2_unlocking_check_writes, and if so schedules writing_action
813
- against the current exec_ctx, to be executed OUTSIDE of the global lock
814
- - eventually writing_action results in grpc_chttp2_terminate_writing being
815
- called, which re-takes the global lock, updates state, checks if we need
816
- to do *another* write immediately, and if so loops back to
817
- start_writing.
818
-
819
- Current problems:
820
- - too much lock entry/exiting
821
- - the writing thread can become stuck indefinitely (punt through the
822
- workqueue periodically to fix) */
823
-
824
- grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global);
825
- switch (t->executor.write_state) {
826
- case GRPC_CHTTP2_WRITING_INACTIVE:
827
- set_write_state(t, covered_by_poller
828
- ? GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER
829
- : GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER,
830
- reason);
614
+ GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0);
615
+
616
+ switch (t->write_state) {
617
+ case GRPC_CHTTP2_WRITE_STATE_IDLE:
618
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, reason);
619
+ GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
620
+ grpc_closure_sched(
621
+ exec_ctx,
622
+ grpc_closure_init(
623
+ &t->write_action_begin_locked, write_action_begin_locked, t,
624
+ grpc_combiner_finally_scheduler(t->combiner, covered_by_poller)),
625
+ GRPC_ERROR_NONE);
831
626
  break;
832
- case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
833
- /* nothing to do: write already requested */
627
+ case GRPC_CHTTP2_WRITE_STATE_WRITING:
628
+ set_write_state(
629
+ exec_ctx, t,
630
+ covered_by_poller
631
+ ? GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER
632
+ : GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE,
633
+ reason);
834
634
  break;
835
- case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
635
+ case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
836
636
  if (covered_by_poller) {
837
- /* upgrade to note poller is available to cover the write */
838
- set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, reason);
637
+ set_write_state(
638
+ exec_ctx, t,
639
+ GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER,
640
+ reason);
839
641
  }
840
642
  break;
841
- case GRPC_CHTTP2_WRITE_SCHEDULED:
842
- /* nothing to do: write already scheduled */
843
- break;
844
- case GRPC_CHTTP2_WRITING:
845
- set_write_state(t,
846
- covered_by_poller ? GRPC_CHTTP2_WRITING_STALE_WITH_POLLER
847
- : GRPC_CHTTP2_WRITING_STALE_NO_POLLER,
848
- reason);
643
+ case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER:
849
644
  break;
850
- case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
851
- /* nothing to do: write already requested */
852
- break;
853
- case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
854
- if (covered_by_poller) {
855
- /* upgrade to note poller is available to cover the write */
856
- set_write_state(t, GRPC_CHTTP2_WRITING_STALE_WITH_POLLER, reason);
857
- }
858
- break;
859
- }
860
- }
861
-
862
- static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
863
- GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED ||
864
- t->executor.write_state == GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER);
865
- if (!t->closed &&
866
- grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) {
867
- set_write_state(t, GRPC_CHTTP2_WRITING, "start_writing");
868
- REF_TRANSPORT(t, "writing");
869
- prevent_endpoint_shutdown(t);
870
- grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL);
871
- } else {
872
- if (t->closed) {
873
- set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE,
874
- "start_writing:transport_closed");
875
- } else {
876
- set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE,
877
- "start_writing:nothing_to_write");
878
- }
879
- end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write"));
880
- if (t->ep && !t->endpoint_reading) {
881
- destroy_endpoint(exec_ctx, t);
882
- }
883
645
  }
884
- }
885
-
886
- static void initiate_writing_locked(grpc_exec_ctx *exec_ctx,
887
- grpc_chttp2_transport *t,
888
- grpc_chttp2_stream *s_unused,
889
- void *arg_ignored) {
890
- start_writing(exec_ctx, t);
891
- UNREF_TRANSPORT(exec_ctx, t, "initiate_writing");
892
- }
893
-
894
- static void initiate_writing(grpc_exec_ctx *exec_ctx, void *arg,
895
- grpc_error *error) {
896
- grpc_chttp2_run_with_global_lock(exec_ctx, arg, NULL, initiate_writing_locked,
897
- NULL, 0);
646
+ GPR_TIMER_END("grpc_chttp2_initiate_write", 0);
898
647
  }
899
648
 
900
649
  void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
901
- grpc_chttp2_transport_global *transport_global,
902
- grpc_chttp2_stream_global *stream_global,
903
- bool covered_by_poller, const char *reason) {
904
- if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed &&
905
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) {
906
- GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
907
- grpc_chttp2_initiate_write(exec_ctx, transport_global, covered_by_poller,
908
- reason);
650
+ grpc_chttp2_transport *t,
651
+ grpc_chttp2_stream *s, bool covered_by_poller,
652
+ const char *reason) {
653
+ if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
654
+ GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
655
+ grpc_chttp2_initiate_write(exec_ctx, t, covered_by_poller, reason);
909
656
  }
910
657
  }
911
658
 
912
- static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
913
- grpc_chttp2_setting_id id, uint32_t value) {
914
- const grpc_chttp2_setting_parameters *sp =
915
- &grpc_chttp2_settings_parameters[id];
916
- uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
917
- if (use_value != value) {
918
- gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
919
- value, use_value);
920
- }
921
- if (use_value != t->global.settings[GRPC_LOCAL_SETTINGS][id]) {
922
- t->global.settings[GRPC_LOCAL_SETTINGS][id] = use_value;
923
- t->global.dirtied_local_settings = 1;
924
- grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "push_setting");
659
+ static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *gt,
660
+ grpc_error *error_ignored) {
661
+ GPR_TIMER_BEGIN("write_action_begin_locked", 0);
662
+ grpc_chttp2_transport *t = gt;
663
+ GPR_ASSERT(t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE);
664
+ if (!t->closed && grpc_chttp2_begin_write(exec_ctx, t)) {
665
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
666
+ "begin writing");
667
+ grpc_closure_sched(exec_ctx, &t->write_action, GRPC_ERROR_NONE);
668
+ } else {
669
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE,
670
+ "begin writing nothing");
671
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing");
925
672
  }
673
+ GPR_TIMER_END("write_action_begin_locked", 0);
926
674
  }
927
675
 
928
- static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
929
- grpc_chttp2_transport *t, grpc_error *error) {
930
- grpc_chttp2_stream_global *stream_global;
931
- while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
932
- &stream_global)) {
933
- fail_pending_writes(exec_ctx, &t->global, stream_global,
934
- GRPC_ERROR_REF(error));
935
- GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
936
- }
937
- GRPC_ERROR_UNREF(error);
676
+ static void write_action(grpc_exec_ctx *exec_ctx, void *gt, grpc_error *error) {
677
+ grpc_chttp2_transport *t = gt;
678
+ GPR_TIMER_BEGIN("write_action", 0);
679
+ grpc_endpoint_write(
680
+ exec_ctx, t->ep, &t->outbuf,
681
+ grpc_closure_init(&t->write_action_end_locked, write_action_end_locked, t,
682
+ grpc_combiner_scheduler(t->combiner, false)));
683
+ GPR_TIMER_END("write_action", 0);
938
684
  }
939
685
 
940
- static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
941
- grpc_chttp2_transport *t,
942
- grpc_chttp2_stream *s_ignored,
943
- void *a) {
944
- grpc_error *error = a;
945
-
946
- allow_endpoint_shutdown_locked(exec_ctx, t);
686
+ static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp,
687
+ grpc_error *error) {
688
+ GPR_TIMER_BEGIN("terminate_writing_with_lock", 0);
689
+ grpc_chttp2_transport *t = tp;
947
690
 
948
691
  if (error != GRPC_ERROR_NONE) {
949
- drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
692
+ close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
950
693
  }
951
694
 
952
- grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
953
-
954
- end_waiting_for_write(exec_ctx, t, error);
695
+ if (t->sent_goaway_state == GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED) {
696
+ t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SENT;
697
+ if (grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
698
+ close_transport_locked(exec_ctx, t, GRPC_ERROR_CREATE("goaway sent"));
699
+ }
700
+ }
955
701
 
956
- switch (t->executor.write_state) {
957
- case GRPC_CHTTP2_WRITING_INACTIVE:
958
- case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
959
- case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
960
- case GRPC_CHTTP2_WRITE_SCHEDULED:
702
+ switch (t->write_state) {
703
+ case GRPC_CHTTP2_WRITE_STATE_IDLE:
961
704
  GPR_UNREACHABLE_CODE(break);
962
- case GRPC_CHTTP2_WRITING:
963
- set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "terminate_writing");
705
+ case GRPC_CHTTP2_WRITE_STATE_WRITING:
706
+ GPR_TIMER_MARK("state=writing", 0);
707
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE,
708
+ "finish writing");
964
709
  break;
965
- case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
966
- set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER,
967
- "terminate_writing");
710
+ case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
711
+ GPR_TIMER_MARK("state=writing_stale_no_poller", 0);
712
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
713
+ "continue writing [!covered]");
714
+ GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
715
+ grpc_closure_run(
716
+ exec_ctx,
717
+ grpc_closure_init(
718
+ &t->write_action_begin_locked, write_action_begin_locked, t,
719
+ grpc_combiner_finally_scheduler(t->combiner, false)),
720
+ GRPC_ERROR_NONE);
968
721
  break;
969
- case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
970
- set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER,
971
- "terminate_writing");
722
+ case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER:
723
+ GPR_TIMER_MARK("state=writing_stale_with_poller", 0);
724
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
725
+ "continue writing [covered]");
726
+ GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
727
+ grpc_closure_run(
728
+ exec_ctx,
729
+ grpc_closure_init(&t->write_action_begin_locked,
730
+ write_action_begin_locked, t,
731
+ grpc_combiner_finally_scheduler(t->combiner, true)),
732
+ GRPC_ERROR_NONE);
972
733
  break;
973
734
  }
974
735
 
975
- if (t->ep && !t->endpoint_reading) {
976
- destroy_endpoint(exec_ctx, t);
977
- }
736
+ grpc_chttp2_end_write(exec_ctx, t, GRPC_ERROR_REF(error));
978
737
 
979
- UNREF_TRANSPORT(exec_ctx, t, "writing");
738
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing");
739
+ GPR_TIMER_END("terminate_writing_with_lock", 0);
980
740
  }
981
741
 
982
- void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
983
- void *transport_writing, grpc_error *error) {
984
- grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
985
- grpc_chttp2_run_with_global_lock(
986
- exec_ctx, t, NULL, terminate_writing_with_lock, GRPC_ERROR_REF(error), 0);
987
- }
988
-
989
- static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
990
- grpc_error *error) {
991
- grpc_chttp2_transport *t = gt;
992
- GPR_TIMER_BEGIN("writing_action", 0);
993
- grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
994
- GPR_TIMER_END("writing_action", 0);
742
+ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
743
+ grpc_chttp2_setting_id id, uint32_t value) {
744
+ const grpc_chttp2_setting_parameters *sp =
745
+ &grpc_chttp2_settings_parameters[id];
746
+ uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
747
+ if (use_value != value) {
748
+ gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
749
+ value, use_value);
750
+ }
751
+ if (use_value != t->settings[GRPC_LOCAL_SETTINGS][id]) {
752
+ t->settings[GRPC_LOCAL_SETTINGS][id] = use_value;
753
+ t->dirtied_local_settings = 1;
754
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "push_setting");
755
+ }
995
756
  }
996
757
 
997
- void grpc_chttp2_add_incoming_goaway(
998
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
999
- uint32_t goaway_error, gpr_slice goaway_text) {
1000
- char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
758
+ void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx,
759
+ grpc_chttp2_transport *t,
760
+ uint32_t goaway_error,
761
+ grpc_slice goaway_text) {
762
+ char *msg = grpc_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
1001
763
  GRPC_CHTTP2_IF_TRACING(
1002
764
  gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg));
1003
- gpr_slice_unref(goaway_text);
1004
- transport_global->seen_goaway = 1;
765
+ grpc_slice_unref_internal(exec_ctx, goaway_text);
766
+ t->seen_goaway = 1;
1005
767
  /* lie: use transient failure from the transport to indicate goaway has been
1006
768
  * received */
1007
769
  connectivity_state_set(
1008
- exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
770
+ exec_ctx, t, GRPC_CHANNEL_TRANSIENT_FAILURE,
1009
771
  grpc_error_set_str(
1010
772
  grpc_error_set_int(GRPC_ERROR_CREATE("GOAWAY received"),
1011
773
  GRPC_ERROR_INT_HTTP2_ERROR,
@@ -1015,65 +777,61 @@ void grpc_chttp2_add_incoming_goaway(
1015
777
  gpr_free(msg);
1016
778
  }
1017
779
 
1018
- static void maybe_start_some_streams(
1019
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) {
1020
- grpc_chttp2_stream_global *stream_global;
780
+ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
781
+ grpc_chttp2_transport *t) {
782
+ grpc_chttp2_stream *s;
1021
783
  uint32_t stream_incoming_window;
1022
784
  /* start streams where we have free grpc_chttp2_stream ids and free
1023
785
  * concurrency */
1024
- while (transport_global->next_stream_id <= MAX_CLIENT_STREAM_ID &&
1025
- transport_global->concurrent_stream_count <
1026
- transport_global
1027
- ->settings[GRPC_PEER_SETTINGS]
1028
- [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] &&
1029
- grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
1030
- &stream_global)) {
786
+ while (t->next_stream_id <= MAX_CLIENT_STREAM_ID &&
787
+ grpc_chttp2_stream_map_size(&t->stream_map) <
788
+ t->settings[GRPC_PEER_SETTINGS]
789
+ [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] &&
790
+ grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
1031
791
  /* safe since we can't (legally) be parsing this stream yet */
1032
- grpc_chttp2_stream_parsing *stream_parsing =
1033
- &STREAM_FROM_GLOBAL(stream_global)->parsing;
1034
792
  GRPC_CHTTP2_IF_TRACING(gpr_log(
1035
793
  GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
1036
- transport_global->is_client ? "CLI" : "SVR", stream_global,
1037
- transport_global->next_stream_id));
794
+ t->is_client ? "CLI" : "SVR", s, t->next_stream_id));
1038
795
 
1039
- GPR_ASSERT(stream_global->id == 0);
1040
- stream_global->id = stream_parsing->id = transport_global->next_stream_id;
1041
- transport_global->next_stream_id += 2;
796
+ GPR_ASSERT(s->id == 0);
797
+ s->id = t->next_stream_id;
798
+ t->next_stream_id += 2;
1042
799
 
1043
- if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
1044
- connectivity_state_set(
1045
- exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
1046
- GRPC_ERROR_CREATE("Stream IDs exhausted"), "no_more_stream_ids");
800
+ if (t->next_stream_id >= MAX_CLIENT_STREAM_ID) {
801
+ connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_TRANSIENT_FAILURE,
802
+ GRPC_ERROR_CREATE("Stream IDs exhausted"),
803
+ "no_more_stream_ids");
1047
804
  }
1048
805
 
1049
- stream_global->outgoing_window =
1050
- transport_global->settings[GRPC_PEER_SETTINGS]
1051
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
1052
- stream_parsing->incoming_window = stream_incoming_window =
1053
- transport_global->settings[GRPC_SENT_SETTINGS]
1054
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
1055
- stream_global->max_recv_bytes =
1056
- GPR_MAX(stream_incoming_window, stream_global->max_recv_bytes);
1057
- grpc_chttp2_stream_map_add(
1058
- &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map,
1059
- stream_global->id, STREAM_FROM_GLOBAL(stream_global));
1060
- stream_global->in_stream_map = true;
1061
- transport_global->concurrent_stream_count++;
1062
- grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, true,
1063
- "new_stream");
806
+ s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
807
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
808
+ s->incoming_window = stream_incoming_window =
809
+ t->settings[GRPC_SENT_SETTINGS]
810
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
811
+ s->max_recv_bytes = GPR_MAX(stream_incoming_window, s->max_recv_bytes);
812
+ grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
813
+ post_destructive_reclaimer(exec_ctx, t);
814
+ grpc_chttp2_become_writable(exec_ctx, t, s, true, "new_stream");
1064
815
  }
1065
816
  /* cancel out streams that will never be started */
1066
- while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
1067
- grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
1068
- &stream_global)) {
1069
- cancel_from_api(exec_ctx, transport_global, stream_global,
1070
- grpc_error_set_int(
1071
- GRPC_ERROR_CREATE("Stream IDs exhausted"),
1072
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
817
+ while (t->next_stream_id >= MAX_CLIENT_STREAM_ID &&
818
+ grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
819
+ grpc_chttp2_cancel_stream(
820
+ exec_ctx, t, s,
821
+ grpc_error_set_int(GRPC_ERROR_CREATE("Stream IDs exhausted"),
822
+ GRPC_ERROR_INT_GRPC_STATUS,
823
+ GRPC_STATUS_UNAVAILABLE));
1073
824
  }
1074
825
  }
1075
826
 
827
+ /* Flag that this closure barrier wants stats to be updated before finishing */
1076
828
  #define CLOSURE_BARRIER_STATS_BIT (1 << 0)
829
+ /* Flag that this closure barrier may be covering a write in a pollset, and so
830
+ we should not complete this closure until we can prove that the write got
831
+ scheduled */
832
+ #define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 1)
833
+ /* First bit of the reference count, stored in the high order bits (with the low
834
+ bits being used for flags defined above) */
1077
835
  #define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
1078
836
 
1079
837
  static grpc_closure *add_closure_barrier(grpc_closure *closure) {
@@ -1081,104 +839,216 @@ static grpc_closure *add_closure_barrier(grpc_closure *closure) {
1081
839
  return closure;
1082
840
  }
1083
841
 
1084
- void grpc_chttp2_complete_closure_step(
1085
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
1086
- grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure,
1087
- grpc_error *error) {
842
+ static void null_then_run_closure(grpc_exec_ctx *exec_ctx,
843
+ grpc_closure **closure, grpc_error *error) {
844
+ grpc_closure *c = *closure;
845
+ *closure = NULL;
846
+ grpc_closure_run(exec_ctx, c, error);
847
+ }
848
+
849
+ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
850
+ grpc_chttp2_transport *t,
851
+ grpc_chttp2_stream *s,
852
+ grpc_closure **pclosure,
853
+ grpc_error *error, const char *desc) {
1088
854
  grpc_closure *closure = *pclosure;
855
+ *pclosure = NULL;
1089
856
  if (closure == NULL) {
1090
857
  GRPC_ERROR_UNREF(error);
1091
858
  return;
1092
859
  }
1093
860
  closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
861
+ if (grpc_http_trace) {
862
+ const char *errstr = grpc_error_string(error);
863
+ gpr_log(GPR_DEBUG,
864
+ "complete_closure_step: %p refs=%d flags=0x%04x desc=%s err=%s",
865
+ closure,
866
+ (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT),
867
+ (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT),
868
+ desc, errstr);
869
+ grpc_error_free_string(errstr);
870
+ }
1094
871
  if (error != GRPC_ERROR_NONE) {
1095
- if (closure->error == GRPC_ERROR_NONE) {
1096
- closure->error =
872
+ if (closure->error_data.error == GRPC_ERROR_NONE) {
873
+ closure->error_data.error =
1097
874
  GRPC_ERROR_CREATE("Error in HTTP transport completing operation");
1098
- closure->error = grpc_error_set_str(
1099
- closure->error, GRPC_ERROR_STR_TARGET_ADDRESS,
1100
- TRANSPORT_FROM_GLOBAL(transport_global)->peer_string);
875
+ closure->error_data.error =
876
+ grpc_error_set_str(closure->error_data.error,
877
+ GRPC_ERROR_STR_TARGET_ADDRESS, t->peer_string);
1101
878
  }
1102
- closure->error = grpc_error_add_child(closure->error, error);
879
+ closure->error_data.error =
880
+ grpc_error_add_child(closure->error_data.error, error);
1103
881
  }
1104
882
  if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
1105
883
  if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
1106
- grpc_transport_move_stats(&stream_global->stats,
1107
- stream_global->collecting_stats);
1108
- stream_global->collecting_stats = NULL;
884
+ grpc_transport_move_stats(&s->stats, s->collecting_stats);
885
+ s->collecting_stats = NULL;
886
+ }
887
+ if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) ||
888
+ !(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) {
889
+ grpc_closure_run(exec_ctx, closure, closure->error_data.error);
890
+ } else {
891
+ grpc_closure_list_append(&t->run_after_write, closure,
892
+ closure->error_data.error);
1109
893
  }
1110
- grpc_exec_ctx_sched(exec_ctx, closure, closure->error, NULL);
1111
894
  }
1112
- *pclosure = NULL;
1113
895
  }
1114
896
 
1115
- static int contains_non_ok_status(
1116
- grpc_chttp2_transport_global *transport_global,
1117
- grpc_metadata_batch *batch) {
897
+ static bool contains_non_ok_status(grpc_metadata_batch *batch) {
1118
898
  grpc_linked_mdelem *l;
1119
899
  for (l = batch->list.head; l; l = l->next) {
1120
900
  if (l->md->key == GRPC_MDSTR_GRPC_STATUS &&
1121
901
  l->md != GRPC_MDELEM_GRPC_STATUS_0) {
1122
- return 1;
902
+ return true;
1123
903
  }
1124
904
  }
1125
- return 0;
905
+ return false;
1126
906
  }
1127
907
 
1128
- static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
908
+ static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx,
909
+ grpc_chttp2_transport *t,
910
+ grpc_chttp2_stream *s) {
911
+ if (s->id != 0 && (!s->write_buffering ||
912
+ s->flow_controlled_buffer.length > t->write_buffer_size)) {
913
+ grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message");
914
+ }
915
+ }
1129
916
 
1130
- static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
917
+ static void add_fetched_slice_locked(grpc_exec_ctx *exec_ctx,
1131
918
  grpc_chttp2_transport *t,
1132
- grpc_chttp2_stream *s, void *stream_op) {
919
+ grpc_chttp2_stream *s) {
920
+ s->fetched_send_message_length +=
921
+ (uint32_t)GRPC_SLICE_LENGTH(s->fetching_slice);
922
+ grpc_slice_buffer_add(&s->flow_controlled_buffer, s->fetching_slice);
923
+ maybe_become_writable_due_to_send_msg(exec_ctx, t, s);
924
+ }
925
+
926
+ static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx,
927
+ grpc_chttp2_transport *t,
928
+ grpc_chttp2_stream *s) {
929
+ for (;;) {
930
+ if (s->fetching_send_message == NULL) {
931
+ /* Stream was cancelled before message fetch completed */
932
+ abort(); /* TODO(ctiller): what cleanup here? */
933
+ return; /* early out */
934
+ }
935
+ if (s->fetched_send_message_length == s->fetching_send_message->length) {
936
+ int64_t notify_offset = s->next_message_end_offset;
937
+ if (notify_offset <= s->flow_controlled_bytes_written) {
938
+ grpc_chttp2_complete_closure_step(
939
+ exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_NONE,
940
+ "fetching_send_message_finished");
941
+ } else {
942
+ grpc_chttp2_write_cb *cb = t->write_cb_pool;
943
+ if (cb == NULL) {
944
+ cb = gpr_malloc(sizeof(*cb));
945
+ } else {
946
+ t->write_cb_pool = cb->next;
947
+ }
948
+ cb->call_at_byte = notify_offset;
949
+ cb->closure = s->fetching_send_message_finished;
950
+ s->fetching_send_message_finished = NULL;
951
+ cb->next = s->on_write_finished_cbs;
952
+ s->on_write_finished_cbs = cb;
953
+ }
954
+ s->fetching_send_message = NULL;
955
+ return; /* early out */
956
+ } else if (grpc_byte_stream_next(exec_ctx, s->fetching_send_message,
957
+ &s->fetching_slice, UINT32_MAX,
958
+ &s->complete_fetch)) {
959
+ add_fetched_slice_locked(exec_ctx, t, s);
960
+ }
961
+ }
962
+ }
963
+
964
+ static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
965
+ grpc_error *error) {
966
+ grpc_chttp2_stream *s = gs;
967
+ grpc_chttp2_transport *t = s->t;
968
+ if (error == GRPC_ERROR_NONE) {
969
+ add_fetched_slice_locked(exec_ctx, t, s);
970
+ continue_fetching_send_locked(exec_ctx, t, s);
971
+ } else {
972
+ /* TODO(ctiller): what to do here */
973
+ abort();
974
+ }
975
+ }
976
+
977
+ static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
978
+
979
+ static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id,
980
+ bool is_client, bool is_initial) {
981
+ for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail;
982
+ md = md->next) {
983
+ gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL",
984
+ is_client ? "CLI" : "SVR", grpc_mdstr_as_c_string(md->md->key),
985
+ grpc_mdstr_as_c_string(md->md->value));
986
+ }
987
+ }
988
+
989
+ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
990
+ grpc_error *error_ignored) {
1133
991
  GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
1134
992
 
1135
993
  grpc_transport_stream_op *op = stream_op;
1136
- grpc_chttp2_transport_global *transport_global = &t->global;
1137
- grpc_chttp2_stream_global *stream_global = &s->global;
994
+ grpc_chttp2_transport *t = op->transport_private.args[0];
995
+ grpc_chttp2_stream *s = op->transport_private.args[1];
996
+
997
+ if (grpc_http_trace) {
998
+ char *str = grpc_transport_stream_op_string(op);
999
+ gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str,
1000
+ op->on_complete);
1001
+ gpr_free(str);
1002
+ if (op->send_initial_metadata) {
1003
+ log_metadata(op->send_initial_metadata, s->id, t->is_client, true);
1004
+ }
1005
+ if (op->send_trailing_metadata) {
1006
+ log_metadata(op->send_trailing_metadata, s->id, t->is_client, false);
1007
+ }
1008
+ }
1138
1009
 
1139
1010
  grpc_closure *on_complete = op->on_complete;
1140
1011
  if (on_complete == NULL) {
1141
- on_complete = grpc_closure_create(do_nothing, NULL);
1012
+ on_complete =
1013
+ grpc_closure_create(do_nothing, NULL, grpc_schedule_on_exec_ctx);
1142
1014
  }
1015
+
1143
1016
  /* use final_data as a barrier until enqueue time; the inital counter is
1144
1017
  dropped at the end of this function */
1145
1018
  on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
1146
- on_complete->error = GRPC_ERROR_NONE;
1019
+ on_complete->error_data.error = GRPC_ERROR_NONE;
1147
1020
 
1148
1021
  if (op->collect_stats != NULL) {
1149
- GPR_ASSERT(stream_global->collecting_stats == NULL);
1150
- stream_global->collecting_stats = op->collect_stats;
1022
+ GPR_ASSERT(s->collecting_stats == NULL);
1023
+ s->collecting_stats = op->collect_stats;
1151
1024
  on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
1152
1025
  }
1153
1026
 
1154
1027
  if (op->cancel_error != GRPC_ERROR_NONE) {
1155
- cancel_from_api(exec_ctx, transport_global, stream_global,
1156
- GRPC_ERROR_REF(op->cancel_error));
1028
+ grpc_chttp2_cancel_stream(exec_ctx, t, s, GRPC_ERROR_REF(op->cancel_error));
1157
1029
  }
1158
1030
 
1159
1031
  if (op->close_error != GRPC_ERROR_NONE) {
1160
- close_from_api(exec_ctx, transport_global, stream_global,
1161
- GRPC_ERROR_REF(op->close_error));
1032
+ close_from_api(exec_ctx, t, s, GRPC_ERROR_REF(op->close_error));
1162
1033
  }
1163
1034
 
1164
1035
  if (op->send_initial_metadata != NULL) {
1165
- GPR_ASSERT(stream_global->send_initial_metadata_finished == NULL);
1166
- stream_global->send_initial_metadata_finished =
1167
- add_closure_barrier(on_complete);
1168
- stream_global->send_initial_metadata = op->send_initial_metadata;
1036
+ GPR_ASSERT(s->send_initial_metadata_finished == NULL);
1037
+ on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
1038
+ s->send_initial_metadata_finished = add_closure_barrier(on_complete);
1039
+ s->send_initial_metadata = op->send_initial_metadata;
1169
1040
  const size_t metadata_size =
1170
1041
  grpc_metadata_batch_size(op->send_initial_metadata);
1171
1042
  const size_t metadata_peer_limit =
1172
- transport_global->settings[GRPC_PEER_SETTINGS]
1173
- [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
1174
- if (transport_global->is_client) {
1175
- stream_global->deadline =
1176
- gpr_time_min(stream_global->deadline,
1177
- stream_global->send_initial_metadata->deadline);
1043
+ t->settings[GRPC_PEER_SETTINGS]
1044
+ [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
1045
+ if (t->is_client) {
1046
+ s->deadline =
1047
+ gpr_time_min(s->deadline, s->send_initial_metadata->deadline);
1178
1048
  }
1179
1049
  if (metadata_size > metadata_peer_limit) {
1180
- cancel_from_api(
1181
- exec_ctx, transport_global, stream_global,
1050
+ grpc_chttp2_cancel_stream(
1051
+ exec_ctx, t, s,
1182
1052
  grpc_error_set_int(
1183
1053
  grpc_error_set_int(
1184
1054
  grpc_error_set_int(
@@ -1188,63 +1058,85 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
1188
1058
  GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit),
1189
1059
  GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
1190
1060
  } else {
1191
- if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
1192
- stream_global->seen_error = true;
1193
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1061
+ if (contains_non_ok_status(op->send_initial_metadata)) {
1062
+ s->seen_error = true;
1194
1063
  }
1195
- if (!stream_global->write_closed) {
1196
- if (transport_global->is_client) {
1197
- GPR_ASSERT(stream_global->id == 0);
1198
- grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
1199
- stream_global);
1200
- maybe_start_some_streams(exec_ctx, transport_global);
1064
+ if (!s->write_closed) {
1065
+ if (t->is_client) {
1066
+ if (!t->closed) {
1067
+ GPR_ASSERT(s->id == 0);
1068
+ grpc_chttp2_list_add_waiting_for_concurrency(t, s);
1069
+ maybe_start_some_streams(exec_ctx, t);
1070
+ } else {
1071
+ grpc_chttp2_cancel_stream(exec_ctx, t, s,
1072
+ GRPC_ERROR_CREATE("Transport closed"));
1073
+ }
1201
1074
  } else {
1202
- GPR_ASSERT(stream_global->id != 0);
1203
- grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
1204
- true, "op.send_initial_metadata");
1075
+ GPR_ASSERT(s->id != 0);
1076
+ grpc_chttp2_become_writable(exec_ctx, t, s, true,
1077
+ "op.send_initial_metadata");
1205
1078
  }
1206
1079
  } else {
1207
- stream_global->send_trailing_metadata = NULL;
1080
+ s->send_initial_metadata = NULL;
1208
1081
  grpc_chttp2_complete_closure_step(
1209
- exec_ctx, transport_global, stream_global,
1210
- &stream_global->send_initial_metadata_finished,
1082
+ exec_ctx, t, s, &s->send_initial_metadata_finished,
1211
1083
  GRPC_ERROR_CREATE(
1212
- "Attempt to send initial metadata after stream was closed"));
1084
+ "Attempt to send initial metadata after stream was closed"),
1085
+ "send_initial_metadata_finished");
1213
1086
  }
1214
1087
  }
1215
1088
  }
1216
1089
 
1217
1090
  if (op->send_message != NULL) {
1218
- GPR_ASSERT(stream_global->send_message_finished == NULL);
1219
- GPR_ASSERT(stream_global->send_message == NULL);
1220
- stream_global->send_message_finished = add_closure_barrier(on_complete);
1221
- if (stream_global->write_closed) {
1091
+ on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
1092
+ s->fetching_send_message_finished = add_closure_barrier(op->on_complete);
1093
+ if (s->write_closed) {
1222
1094
  grpc_chttp2_complete_closure_step(
1223
- exec_ctx, transport_global, stream_global,
1224
- &stream_global->send_message_finished,
1225
- GRPC_ERROR_CREATE("Attempt to send message after stream was closed"));
1095
+ exec_ctx, t, s, &s->fetching_send_message_finished,
1096
+ GRPC_ERROR_CREATE("Attempt to send message after stream was closed"),
1097
+ "fetching_send_message_finished");
1226
1098
  } else {
1227
- stream_global->send_message = op->send_message;
1228
- if (stream_global->id != 0) {
1229
- grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
1230
- true, "op.send_message");
1099
+ GPR_ASSERT(s->fetching_send_message == NULL);
1100
+ uint8_t *frame_hdr =
1101
+ grpc_slice_buffer_tiny_add(&s->flow_controlled_buffer, 5);
1102
+ uint32_t flags = op->send_message->flags;
1103
+ frame_hdr[0] = (flags & GRPC_WRITE_INTERNAL_COMPRESS) != 0;
1104
+ size_t len = op->send_message->length;
1105
+ frame_hdr[1] = (uint8_t)(len >> 24);
1106
+ frame_hdr[2] = (uint8_t)(len >> 16);
1107
+ frame_hdr[3] = (uint8_t)(len >> 8);
1108
+ frame_hdr[4] = (uint8_t)(len);
1109
+ s->fetching_send_message = op->send_message;
1110
+ s->fetched_send_message_length = 0;
1111
+ s->next_message_end_offset = s->flow_controlled_bytes_written +
1112
+ (int64_t)s->flow_controlled_buffer.length +
1113
+ (int64_t)len;
1114
+ s->complete_fetch_covered_by_poller = op->covered_by_poller;
1115
+ if (flags & GRPC_WRITE_BUFFER_HINT) {
1116
+ s->next_message_end_offset -= t->write_buffer_size;
1117
+ s->write_buffering = true;
1118
+ } else {
1119
+ s->write_buffering = false;
1231
1120
  }
1121
+ continue_fetching_send_locked(exec_ctx, t, s);
1122
+ maybe_become_writable_due_to_send_msg(exec_ctx, t, s);
1232
1123
  }
1233
1124
  }
1234
1125
 
1235
1126
  if (op->send_trailing_metadata != NULL) {
1236
- GPR_ASSERT(stream_global->send_trailing_metadata_finished == NULL);
1237
- stream_global->send_trailing_metadata_finished =
1238
- add_closure_barrier(on_complete);
1239
- stream_global->send_trailing_metadata = op->send_trailing_metadata;
1127
+ GPR_ASSERT(s->send_trailing_metadata_finished == NULL);
1128
+ on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
1129
+ s->send_trailing_metadata_finished = add_closure_barrier(on_complete);
1130
+ s->send_trailing_metadata = op->send_trailing_metadata;
1131
+ s->write_buffering = false;
1240
1132
  const size_t metadata_size =
1241
1133
  grpc_metadata_batch_size(op->send_trailing_metadata);
1242
1134
  const size_t metadata_peer_limit =
1243
- transport_global->settings[GRPC_PEER_SETTINGS]
1244
- [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
1135
+ t->settings[GRPC_PEER_SETTINGS]
1136
+ [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
1245
1137
  if (metadata_size > metadata_peer_limit) {
1246
- cancel_from_api(
1247
- exec_ctx, transport_global, stream_global,
1138
+ grpc_chttp2_cancel_stream(
1139
+ exec_ctx, t, s,
1248
1140
  grpc_error_set_int(
1249
1141
  grpc_error_set_int(
1250
1142
  grpc_error_set_int(
@@ -1254,135 +1146,139 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
1254
1146
  GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit),
1255
1147
  GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
1256
1148
  } else {
1257
- if (contains_non_ok_status(transport_global,
1258
- op->send_trailing_metadata)) {
1259
- stream_global->seen_error = true;
1260
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1149
+ if (contains_non_ok_status(op->send_trailing_metadata)) {
1150
+ s->seen_error = true;
1261
1151
  }
1262
- if (stream_global->write_closed) {
1263
- stream_global->send_trailing_metadata = NULL;
1152
+ if (s->write_closed) {
1153
+ s->send_trailing_metadata = NULL;
1264
1154
  grpc_chttp2_complete_closure_step(
1265
- exec_ctx, transport_global, stream_global,
1266
- &stream_global->send_trailing_metadata_finished,
1155
+ exec_ctx, t, s, &s->send_trailing_metadata_finished,
1267
1156
  grpc_metadata_batch_is_empty(op->send_trailing_metadata)
1268
1157
  ? GRPC_ERROR_NONE
1269
1158
  : GRPC_ERROR_CREATE("Attempt to send trailing metadata after "
1270
- "stream was closed"));
1271
- } else if (stream_global->id != 0) {
1159
+ "stream was closed"),
1160
+ "send_trailing_metadata_finished");
1161
+ } else if (s->id != 0) {
1272
1162
  /* TODO(ctiller): check if there's flow control for any outstanding
1273
1163
  bytes before going writable */
1274
- grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
1275
- true, "op.send_trailing_metadata");
1164
+ grpc_chttp2_become_writable(exec_ctx, t, s, true,
1165
+ "op.send_trailing_metadata");
1276
1166
  }
1277
1167
  }
1278
1168
  }
1279
1169
 
1280
1170
  if (op->recv_initial_metadata != NULL) {
1281
- GPR_ASSERT(stream_global->recv_initial_metadata_ready == NULL);
1282
- stream_global->recv_initial_metadata_ready =
1283
- op->recv_initial_metadata_ready;
1284
- stream_global->recv_initial_metadata = op->recv_initial_metadata;
1285
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1171
+ GPR_ASSERT(s->recv_initial_metadata_ready == NULL);
1172
+ s->recv_initial_metadata_ready = op->recv_initial_metadata_ready;
1173
+ s->recv_initial_metadata = op->recv_initial_metadata;
1174
+ grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
1286
1175
  }
1287
1176
 
1288
1177
  if (op->recv_message != NULL) {
1289
- GPR_ASSERT(stream_global->recv_message_ready == NULL);
1290
- stream_global->recv_message_ready = op->recv_message_ready;
1291
- stream_global->recv_message = op->recv_message;
1292
- if (stream_global->id != 0 &&
1293
- (stream_global->incoming_frames.head == NULL ||
1294
- stream_global->incoming_frames.head->is_tail)) {
1295
- incoming_byte_stream_update_flow_control(
1296
- exec_ctx, transport_global, stream_global,
1297
- transport_global->stream_lookahead, 0);
1178
+ GPR_ASSERT(s->recv_message_ready == NULL);
1179
+ s->recv_message_ready = op->recv_message_ready;
1180
+ s->recv_message = op->recv_message;
1181
+ if (s->id != 0 &&
1182
+ (s->incoming_frames.head == NULL || s->incoming_frames.head->is_tail)) {
1183
+ incoming_byte_stream_update_flow_control(exec_ctx, t, s,
1184
+ t->stream_lookahead, 0);
1298
1185
  }
1299
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1186
+ grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
1300
1187
  }
1301
1188
 
1302
1189
  if (op->recv_trailing_metadata != NULL) {
1303
- GPR_ASSERT(stream_global->recv_trailing_metadata_finished == NULL);
1304
- stream_global->recv_trailing_metadata_finished =
1305
- add_closure_barrier(on_complete);
1306
- stream_global->recv_trailing_metadata = op->recv_trailing_metadata;
1307
- stream_global->final_metadata_requested = true;
1308
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1190
+ GPR_ASSERT(s->recv_trailing_metadata_finished == NULL);
1191
+ s->recv_trailing_metadata_finished = add_closure_barrier(on_complete);
1192
+ s->recv_trailing_metadata = op->recv_trailing_metadata;
1193
+ s->final_metadata_requested = true;
1194
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1309
1195
  }
1310
1196
 
1311
- grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
1312
- &on_complete, GRPC_ERROR_NONE);
1197
+ grpc_chttp2_complete_closure_step(exec_ctx, t, s, &on_complete,
1198
+ GRPC_ERROR_NONE, "op->on_complete");
1313
1199
 
1314
1200
  GPR_TIMER_END("perform_stream_op_locked", 0);
1201
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "perform_stream_op");
1315
1202
  }
1316
1203
 
1317
1204
  static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1318
1205
  grpc_stream *gs, grpc_transport_stream_op *op) {
1206
+ GPR_TIMER_BEGIN("perform_stream_op", 0);
1319
1207
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
1320
1208
  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
1321
- grpc_chttp2_run_with_global_lock(exec_ctx, t, s, perform_stream_op_locked, op,
1322
- sizeof(*op));
1209
+
1210
+ if (grpc_http_trace) {
1211
+ char *str = grpc_transport_stream_op_string(op);
1212
+ gpr_log(GPR_DEBUG, "perform_stream_op[s=%p/%d]: %s", s, s->id, str);
1213
+ gpr_free(str);
1214
+ }
1215
+
1216
+ op->transport_private.args[0] = gt;
1217
+ op->transport_private.args[1] = gs;
1218
+ GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
1219
+ grpc_closure_sched(
1220
+ exec_ctx,
1221
+ grpc_closure_init(
1222
+ &op->transport_private.closure, perform_stream_op_locked, op,
1223
+ grpc_combiner_scheduler(t->combiner, op->covered_by_poller)),
1224
+ GRPC_ERROR_NONE);
1225
+ GPR_TIMER_END("perform_stream_op", 0);
1323
1226
  }
1324
1227
 
1325
1228
  static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1326
1229
  grpc_closure *on_recv) {
1327
1230
  grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
1328
- p->next = &t->global.pings;
1231
+ p->next = &t->pings;
1329
1232
  p->prev = p->next->prev;
1330
1233
  p->prev->next = p->next->prev = p;
1331
- p->id[0] = (uint8_t)((t->global.ping_counter >> 56) & 0xff);
1332
- p->id[1] = (uint8_t)((t->global.ping_counter >> 48) & 0xff);
1333
- p->id[2] = (uint8_t)((t->global.ping_counter >> 40) & 0xff);
1334
- p->id[3] = (uint8_t)((t->global.ping_counter >> 32) & 0xff);
1335
- p->id[4] = (uint8_t)((t->global.ping_counter >> 24) & 0xff);
1336
- p->id[5] = (uint8_t)((t->global.ping_counter >> 16) & 0xff);
1337
- p->id[6] = (uint8_t)((t->global.ping_counter >> 8) & 0xff);
1338
- p->id[7] = (uint8_t)(t->global.ping_counter & 0xff);
1234
+ p->id[0] = (uint8_t)((t->ping_counter >> 56) & 0xff);
1235
+ p->id[1] = (uint8_t)((t->ping_counter >> 48) & 0xff);
1236
+ p->id[2] = (uint8_t)((t->ping_counter >> 40) & 0xff);
1237
+ p->id[3] = (uint8_t)((t->ping_counter >> 32) & 0xff);
1238
+ p->id[4] = (uint8_t)((t->ping_counter >> 24) & 0xff);
1239
+ p->id[5] = (uint8_t)((t->ping_counter >> 16) & 0xff);
1240
+ p->id[6] = (uint8_t)((t->ping_counter >> 8) & 0xff);
1241
+ p->id[7] = (uint8_t)(t->ping_counter & 0xff);
1242
+ t->ping_counter++;
1339
1243
  p->on_recv = on_recv;
1340
- gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id));
1341
- grpc_chttp2_initiate_write(exec_ctx, &t->global, true, "send_ping");
1244
+ grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_ping_create(0, p->id));
1245
+ grpc_chttp2_initiate_write(exec_ctx, t, true, "send_ping");
1342
1246
  }
1343
1247
 
1344
- static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1345
- grpc_chttp2_stream *s, void *opaque_8bytes) {
1248
+ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1249
+ const uint8_t *opaque_8bytes) {
1346
1250
  grpc_chttp2_outstanding_ping *ping;
1347
- grpc_chttp2_transport_global *transport_global = &t->global;
1348
- for (ping = transport_global->pings.next; ping != &transport_global->pings;
1349
- ping = ping->next) {
1251
+ for (ping = t->pings.next; ping != &t->pings; ping = ping->next) {
1350
1252
  if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
1351
- grpc_exec_ctx_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE, NULL);
1253
+ grpc_closure_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE);
1352
1254
  ping->next->prev = ping->prev;
1353
1255
  ping->prev->next = ping->next;
1354
1256
  gpr_free(ping);
1355
- break;
1257
+ return;
1356
1258
  }
1357
1259
  }
1260
+ char *msg = gpr_dump((const char *)opaque_8bytes, 8, GPR_DUMP_HEX);
1261
+ char *from = grpc_endpoint_get_peer(t->ep);
1262
+ gpr_log(GPR_DEBUG, "Unknown ping response from %s: %s", from, msg);
1263
+ gpr_free(from);
1264
+ gpr_free(msg);
1358
1265
  }
1359
1266
 
1360
- void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
1361
- grpc_chttp2_transport_parsing *transport_parsing,
1362
- const uint8_t *opaque_8bytes) {
1363
- grpc_chttp2_run_with_global_lock(
1364
- exec_ctx, TRANSPORT_FROM_PARSING(transport_parsing), NULL,
1365
- ack_ping_locked, (void *)opaque_8bytes, 8);
1267
+ static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1268
+ grpc_chttp2_error_code error, grpc_slice data) {
1269
+ t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED;
1270
+ grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)error, data,
1271
+ &t->qbuf);
1272
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent");
1366
1273
  }
1367
1274
 
1368
1275
  static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1369
- grpc_chttp2_transport *t,
1370
- grpc_chttp2_stream *s_unused,
1371
- void *stream_op) {
1276
+ void *stream_op,
1277
+ grpc_error *error_ignored) {
1372
1278
  grpc_transport_op *op = stream_op;
1279
+ grpc_chttp2_transport *t = op->transport_private.args[0];
1373
1280
  grpc_error *close_transport = op->disconnect_with_error;
1374
1281
 
1375
- /* If there's a set_accept_stream ensure that we're not parsing
1376
- to avoid changing things out from underneath */
1377
- if (t->executor.parsing_active && op->set_accept_stream) {
1378
- GPR_ASSERT(t->post_parsing_op == NULL);
1379
- t->post_parsing_op = gpr_malloc(sizeof(*op));
1380
- memcpy(t->post_parsing_op, op, sizeof(*op));
1381
- return;
1382
- }
1383
-
1384
- grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
1385
-
1386
1282
  if (op->on_connectivity_state_change != NULL) {
1387
1283
  grpc_connectivity_state_notify_on_state_change(
1388
1284
  exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state,
@@ -1390,15 +1286,9 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1390
1286
  }
1391
1287
 
1392
1288
  if (op->send_goaway) {
1393
- t->global.sent_goaway = 1;
1394
- grpc_chttp2_goaway_append(
1395
- t->global.last_incoming_stream_id,
1396
- (uint32_t)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
1397
- gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
1398
- close_transport = grpc_chttp2_has_streams(t)
1399
- ? GRPC_ERROR_NONE
1400
- : GRPC_ERROR_CREATE("GOAWAY sent");
1401
- grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "goaway_sent");
1289
+ send_goaway(exec_ctx, t,
1290
+ grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
1291
+ grpc_slice_ref_internal(*op->goaway_message));
1402
1292
  }
1403
1293
 
1404
1294
  if (op->set_accept_stream) {
@@ -1408,11 +1298,11 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1408
1298
  }
1409
1299
 
1410
1300
  if (op->bind_pollset) {
1411
- add_to_pollset_locked(exec_ctx, t, NULL, op->bind_pollset);
1301
+ grpc_endpoint_add_to_pollset(exec_ctx, t->ep, op->bind_pollset);
1412
1302
  }
1413
1303
 
1414
1304
  if (op->bind_pollset_set) {
1415
- add_to_pollset_set_locked(exec_ctx, t, NULL, op->bind_pollset_set);
1305
+ grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, op->bind_pollset_set);
1416
1306
  }
1417
1307
 
1418
1308
  if (op->send_ping) {
@@ -1422,144 +1312,133 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1422
1312
  if (close_transport != GRPC_ERROR_NONE) {
1423
1313
  close_transport_locked(exec_ctx, t, close_transport);
1424
1314
  }
1315
+
1316
+ grpc_closure_run(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
1317
+
1318
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "transport_op");
1425
1319
  }
1426
1320
 
1427
1321
  static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1428
1322
  grpc_transport_op *op) {
1429
1323
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
1430
- grpc_chttp2_run_with_global_lock(
1431
- exec_ctx, t, NULL, perform_transport_op_locked, op, sizeof(*op));
1324
+ char *msg = grpc_transport_op_string(op);
1325
+ gpr_free(msg);
1326
+ op->transport_private.args[0] = gt;
1327
+ GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op");
1328
+ grpc_closure_sched(
1329
+ exec_ctx, grpc_closure_init(&op->transport_private.closure,
1330
+ perform_transport_op_locked, op,
1331
+ grpc_combiner_scheduler(t->combiner, false)),
1332
+ GRPC_ERROR_NONE);
1432
1333
  }
1433
1334
 
1434
1335
  /*******************************************************************************
1435
1336
  * INPUT PROCESSING - GENERAL
1436
1337
  */
1437
1338
 
1438
- static void check_read_ops(grpc_exec_ctx *exec_ctx,
1439
- grpc_chttp2_transport_global *transport_global) {
1440
- grpc_chttp2_stream_global *stream_global;
1339
+ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
1340
+ grpc_chttp2_transport *t,
1341
+ grpc_chttp2_stream *s) {
1441
1342
  grpc_byte_stream *bs;
1442
- while (
1443
- grpc_chttp2_list_pop_check_read_ops(transport_global, &stream_global)) {
1444
- if (stream_global->recv_initial_metadata_ready != NULL &&
1445
- stream_global->published_initial_metadata) {
1446
- if (stream_global->seen_error) {
1447
- while ((bs = grpc_chttp2_incoming_frame_queue_pop(
1448
- &stream_global->incoming_frames)) != NULL) {
1449
- incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1450
- }
1451
- if (stream_global->exceeded_metadata_size) {
1452
- cancel_from_api(
1453
- exec_ctx, transport_global, stream_global,
1454
- grpc_error_set_int(
1455
- GRPC_ERROR_CREATE(
1456
- "received initial metadata size exceeds limit"),
1457
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
1458
- }
1343
+ if (s->recv_initial_metadata_ready != NULL &&
1344
+ s->published_metadata[0] != GRPC_METADATA_NOT_PUBLISHED) {
1345
+ if (s->seen_error) {
1346
+ while ((bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames)) !=
1347
+ NULL) {
1348
+ incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE);
1459
1349
  }
1460
- grpc_chttp2_incoming_metadata_buffer_publish(
1461
- &stream_global->received_initial_metadata,
1462
- stream_global->recv_initial_metadata);
1463
- grpc_exec_ctx_sched(exec_ctx, stream_global->recv_initial_metadata_ready,
1464
- GRPC_ERROR_NONE, NULL);
1465
- stream_global->recv_initial_metadata_ready = NULL;
1466
1350
  }
1467
- if (stream_global->recv_message_ready != NULL) {
1468
- while (stream_global->final_metadata_requested &&
1469
- stream_global->seen_error &&
1470
- (bs = grpc_chttp2_incoming_frame_queue_pop(
1471
- &stream_global->incoming_frames)) != NULL) {
1472
- incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1473
- }
1474
- if (stream_global->incoming_frames.head != NULL) {
1475
- *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
1476
- &stream_global->incoming_frames);
1477
- GPR_ASSERT(*stream_global->recv_message != NULL);
1478
- grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
1479
- GRPC_ERROR_NONE, NULL);
1480
- stream_global->recv_message_ready = NULL;
1481
- } else if (stream_global->published_trailing_metadata) {
1482
- *stream_global->recv_message = NULL;
1483
- grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
1484
- GRPC_ERROR_NONE, NULL);
1485
- stream_global->recv_message_ready = NULL;
1486
- }
1351
+ grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[0],
1352
+ s->recv_initial_metadata);
1353
+ null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready,
1354
+ GRPC_ERROR_NONE);
1355
+ }
1356
+ }
1357
+
1358
+ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
1359
+ grpc_chttp2_transport *t,
1360
+ grpc_chttp2_stream *s) {
1361
+ grpc_byte_stream *bs;
1362
+ if (s->recv_message_ready != NULL) {
1363
+ while (s->final_metadata_requested && s->seen_error &&
1364
+ (bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames)) !=
1365
+ NULL) {
1366
+ incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE);
1487
1367
  }
1488
- if (stream_global->recv_trailing_metadata_finished != NULL &&
1489
- stream_global->read_closed && stream_global->write_closed) {
1490
- if (stream_global->seen_error) {
1491
- while ((bs = grpc_chttp2_incoming_frame_queue_pop(
1492
- &stream_global->incoming_frames)) != NULL) {
1493
- incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1494
- }
1495
- if (stream_global->exceeded_metadata_size) {
1496
- cancel_from_api(
1497
- exec_ctx, transport_global, stream_global,
1498
- grpc_error_set_int(
1499
- GRPC_ERROR_CREATE(
1500
- "received trailing metadata size exceeds limit"),
1501
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
1502
- }
1503
- }
1504
- if (stream_global->all_incoming_byte_streams_finished) {
1505
- grpc_chttp2_incoming_metadata_buffer_publish(
1506
- &stream_global->received_trailing_metadata,
1507
- stream_global->recv_trailing_metadata);
1508
- grpc_chttp2_complete_closure_step(
1509
- exec_ctx, transport_global, stream_global,
1510
- &stream_global->recv_trailing_metadata_finished, GRPC_ERROR_NONE);
1368
+ if (s->incoming_frames.head != NULL) {
1369
+ *s->recv_message =
1370
+ grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames);
1371
+ GPR_ASSERT(*s->recv_message != NULL);
1372
+ null_then_run_closure(exec_ctx, &s->recv_message_ready, GRPC_ERROR_NONE);
1373
+ } else if (s->published_metadata[1] != GRPC_METADATA_NOT_PUBLISHED) {
1374
+ *s->recv_message = NULL;
1375
+ null_then_run_closure(exec_ctx, &s->recv_message_ready, GRPC_ERROR_NONE);
1376
+ }
1377
+ }
1378
+ }
1379
+
1380
+ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
1381
+ grpc_chttp2_transport *t,
1382
+ grpc_chttp2_stream *s) {
1383
+ grpc_byte_stream *bs;
1384
+ grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
1385
+ if (s->recv_trailing_metadata_finished != NULL && s->read_closed &&
1386
+ s->write_closed) {
1387
+ if (s->seen_error) {
1388
+ while ((bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames)) !=
1389
+ NULL) {
1390
+ incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE);
1511
1391
  }
1512
1392
  }
1393
+ if (s->all_incoming_byte_streams_finished &&
1394
+ s->recv_trailing_metadata_finished != NULL) {
1395
+ grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1],
1396
+ s->recv_trailing_metadata);
1397
+ grpc_chttp2_complete_closure_step(
1398
+ exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE,
1399
+ "recv_trailing_metadata_finished");
1400
+ }
1513
1401
  }
1514
1402
  }
1515
1403
 
1516
- static void decrement_active_streams_locked(
1517
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
1518
- grpc_chttp2_stream_global *stream_global) {
1519
- if ((stream_global->all_incoming_byte_streams_finished =
1520
- gpr_unref(&stream_global->active_streams))) {
1521
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1404
+ static void decrement_active_streams_locked(grpc_exec_ctx *exec_ctx,
1405
+ grpc_chttp2_transport *t,
1406
+ grpc_chttp2_stream *s) {
1407
+ if ((s->all_incoming_byte_streams_finished = gpr_unref(&s->active_streams))) {
1408
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1522
1409
  }
1523
1410
  }
1524
1411
 
1525
1412
  static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1526
1413
  uint32_t id, grpc_error *error) {
1527
- size_t new_stream_count;
1528
- grpc_chttp2_stream *s =
1529
- grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
1530
- if (!s) {
1531
- s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
1532
- }
1414
+ grpc_chttp2_stream *s = grpc_chttp2_stream_map_delete(&t->stream_map, id);
1533
1415
  GPR_ASSERT(s);
1534
- s->global.in_stream_map = false;
1535
- if (t->parsing.incoming_stream == &s->parsing) {
1536
- t->parsing.incoming_stream = NULL;
1537
- grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing);
1416
+ if (t->incoming_stream == s) {
1417
+ t->incoming_stream = NULL;
1418
+ grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
1538
1419
  }
1539
- if (s->parsing.data_parser.parsing_frame != NULL) {
1420
+ if (s->data_parser.parsing_frame != NULL) {
1540
1421
  grpc_chttp2_incoming_byte_stream_finished(
1541
- exec_ctx, s->parsing.data_parser.parsing_frame, GRPC_ERROR_REF(error),
1542
- 0);
1543
- s->parsing.data_parser.parsing_frame = NULL;
1422
+ exec_ctx, s->data_parser.parsing_frame, GRPC_ERROR_REF(error));
1423
+ s->data_parser.parsing_frame = NULL;
1544
1424
  }
1545
1425
 
1546
- if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
1547
- close_transport_locked(
1548
- exec_ctx, t, GRPC_ERROR_CREATE_REFERENCING(
1549
- "Last stream closed after sending GOAWAY", &error, 1));
1426
+ if (grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
1427
+ post_benign_reclaimer(exec_ctx, t);
1428
+ if (t->sent_goaway_state == GRPC_CHTTP2_GOAWAY_SENT) {
1429
+ close_transport_locked(
1430
+ exec_ctx, t,
1431
+ GRPC_ERROR_CREATE_REFERENCING(
1432
+ "Last stream closed after sending GOAWAY", &error, 1));
1433
+ }
1550
1434
  }
1551
- if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
1552
- GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
1435
+ if (grpc_chttp2_list_remove_writable_stream(t, s)) {
1436
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:remove_stream");
1553
1437
  }
1554
1438
 
1555
- new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
1556
- grpc_chttp2_stream_map_size(&t->new_stream_map);
1557
- GPR_ASSERT(new_stream_count <= UINT32_MAX);
1558
- if (new_stream_count != t->global.concurrent_stream_count) {
1559
- t->global.concurrent_stream_count = (uint32_t)new_stream_count;
1560
- maybe_start_some_streams(exec_ctx, &t->global);
1561
- }
1562
1439
  GRPC_ERROR_UNREF(error);
1440
+
1441
+ maybe_start_some_streams(exec_ctx, t);
1563
1442
  }
1564
1443
 
1565
1444
  static void status_codes_from_error(grpc_error *error, gpr_timespec deadline,
@@ -1589,23 +1468,20 @@ static void status_codes_from_error(grpc_error *error, gpr_timespec deadline,
1589
1468
  }
1590
1469
  }
1591
1470
 
1592
- static void cancel_from_api(grpc_exec_ctx *exec_ctx,
1593
- grpc_chttp2_transport_global *transport_global,
1594
- grpc_chttp2_stream_global *stream_global,
1595
- grpc_error *due_to_error) {
1596
- if (!stream_global->read_closed || !stream_global->write_closed) {
1471
+ void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
1472
+ grpc_chttp2_transport *t, grpc_chttp2_stream *s,
1473
+ grpc_error *due_to_error) {
1474
+ if (!s->read_closed || !s->write_closed) {
1597
1475
  grpc_status_code grpc_status;
1598
1476
  grpc_chttp2_error_code http_error;
1599
- status_codes_from_error(due_to_error, stream_global->deadline, &http_error,
1477
+ status_codes_from_error(due_to_error, s->deadline, &http_error,
1600
1478
  &grpc_status);
1601
1479
 
1602
- if (stream_global->id != 0) {
1603
- gpr_slice_buffer_add(
1604
- &transport_global->qbuf,
1605
- grpc_chttp2_rst_stream_create(stream_global->id, (uint32_t)http_error,
1606
- &stream_global->stats.outgoing));
1607
- grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
1608
- "rst_stream");
1480
+ if (s->id != 0) {
1481
+ grpc_slice_buffer_add(
1482
+ &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
1483
+ &s->stats.outgoing));
1484
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream");
1609
1485
  }
1610
1486
 
1611
1487
  const char *msg =
@@ -1615,26 +1491,22 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
1615
1491
  free_msg = true;
1616
1492
  msg = grpc_error_string(due_to_error);
1617
1493
  }
1618
- gpr_slice msg_slice = gpr_slice_from_copied_string(msg);
1619
- grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
1620
- grpc_status, &msg_slice);
1494
+ grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
1495
+ grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
1621
1496
  if (free_msg) grpc_error_free_string(msg);
1622
1497
  }
1623
- if (due_to_error != GRPC_ERROR_NONE && !stream_global->seen_error) {
1624
- stream_global->seen_error = true;
1625
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1498
+ if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) {
1499
+ s->seen_error = true;
1500
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1626
1501
  }
1627
- grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1628
- 1, due_to_error);
1502
+ grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error);
1629
1503
  }
1630
1504
 
1631
- void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
1632
- grpc_chttp2_transport_global *transport_global,
1633
- grpc_chttp2_stream_global *stream_global,
1634
- grpc_status_code status, gpr_slice *slice) {
1505
+ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1506
+ grpc_chttp2_stream *s, grpc_status_code status,
1507
+ grpc_slice *slice) {
1635
1508
  if (status != GRPC_STATUS_OK) {
1636
- stream_global->seen_error = true;
1637
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1509
+ s->seen_error = true;
1638
1510
  }
1639
1511
  /* stream_global->recv_trailing_metadata_finished gives us a
1640
1512
  last chance replacement: we've received trailing metadata,
@@ -1642,26 +1514,27 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
1642
1514
  to the upper layers - drop what we've got, and then publish
1643
1515
  what we want - which is safe because we haven't told anyone
1644
1516
  about the metadata yet */
1645
- if (!stream_global->published_trailing_metadata ||
1646
- stream_global->recv_trailing_metadata_finished != NULL) {
1517
+ if (s->published_metadata[1] == GRPC_METADATA_NOT_PUBLISHED ||
1518
+ s->recv_trailing_metadata_finished != NULL) {
1647
1519
  char status_string[GPR_LTOA_MIN_BUFSIZE];
1648
1520
  gpr_ltoa(status, status_string);
1649
1521
  grpc_chttp2_incoming_metadata_buffer_add(
1650
- &stream_global->received_trailing_metadata,
1651
- grpc_mdelem_from_metadata_strings(
1652
- GRPC_MDSTR_GRPC_STATUS, grpc_mdstr_from_string(status_string)));
1522
+ &s->metadata_buffer[1], grpc_mdelem_from_metadata_strings(
1523
+ exec_ctx, GRPC_MDSTR_GRPC_STATUS,
1524
+ grpc_mdstr_from_string(status_string)));
1653
1525
  if (slice) {
1654
1526
  grpc_chttp2_incoming_metadata_buffer_add(
1655
- &stream_global->received_trailing_metadata,
1527
+ &s->metadata_buffer[1],
1656
1528
  grpc_mdelem_from_metadata_strings(
1657
- GRPC_MDSTR_GRPC_MESSAGE,
1658
- grpc_mdstr_from_slice(gpr_slice_ref(*slice))));
1529
+ exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
1530
+ grpc_mdstr_from_slice(exec_ctx,
1531
+ grpc_slice_ref_internal(*slice))));
1659
1532
  }
1660
- stream_global->published_trailing_metadata = true;
1661
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1533
+ s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
1534
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1662
1535
  }
1663
1536
  if (slice) {
1664
- gpr_slice_unref(*slice);
1537
+ grpc_slice_unref_internal(exec_ctx, *slice);
1665
1538
  }
1666
1539
  }
1667
1540
 
@@ -1676,112 +1549,118 @@ static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) {
1676
1549
  ++*nrefs;
1677
1550
  }
1678
1551
 
1679
- static grpc_error *removal_error(grpc_error *extra_error,
1680
- grpc_chttp2_stream_global *stream_global) {
1552
+ static grpc_error *removal_error(grpc_error *extra_error, grpc_chttp2_stream *s,
1553
+ const char *master_error_msg) {
1681
1554
  grpc_error *refs[3];
1682
1555
  size_t nrefs = 0;
1683
- add_error(stream_global->read_closed_error, refs, &nrefs);
1684
- add_error(stream_global->write_closed_error, refs, &nrefs);
1556
+ add_error(s->read_closed_error, refs, &nrefs);
1557
+ add_error(s->write_closed_error, refs, &nrefs);
1685
1558
  add_error(extra_error, refs, &nrefs);
1686
1559
  grpc_error *error = GRPC_ERROR_NONE;
1687
1560
  if (nrefs > 0) {
1688
- error = GRPC_ERROR_CREATE_REFERENCING("Failed due to stream removal", refs,
1689
- nrefs);
1561
+ error = GRPC_ERROR_CREATE_REFERENCING(master_error_msg, refs, nrefs);
1690
1562
  }
1691
1563
  GRPC_ERROR_UNREF(extra_error);
1692
1564
  return error;
1693
1565
  }
1694
1566
 
1695
- static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
1696
- grpc_chttp2_transport_global *transport_global,
1697
- grpc_chttp2_stream_global *stream_global,
1698
- grpc_error *error) {
1699
- error = removal_error(error, stream_global);
1700
- stream_global->send_message = NULL;
1567
+ void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx,
1568
+ grpc_chttp2_transport *t,
1569
+ grpc_chttp2_stream *s, grpc_error *error) {
1570
+ error =
1571
+ removal_error(error, s, "Pending writes failed due to stream closure");
1572
+ s->send_initial_metadata = NULL;
1701
1573
  grpc_chttp2_complete_closure_step(
1702
- exec_ctx, transport_global, stream_global,
1703
- &stream_global->send_initial_metadata_finished, GRPC_ERROR_REF(error));
1574
+ exec_ctx, t, s, &s->send_initial_metadata_finished, GRPC_ERROR_REF(error),
1575
+ "send_initial_metadata_finished");
1576
+
1577
+ s->send_trailing_metadata = NULL;
1578
+ grpc_chttp2_complete_closure_step(
1579
+ exec_ctx, t, s, &s->send_trailing_metadata_finished,
1580
+ GRPC_ERROR_REF(error), "send_trailing_metadata_finished");
1581
+
1582
+ s->fetching_send_message = NULL;
1704
1583
  grpc_chttp2_complete_closure_step(
1705
- exec_ctx, transport_global, stream_global,
1706
- &stream_global->send_trailing_metadata_finished, GRPC_ERROR_REF(error));
1707
- grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
1708
- &stream_global->send_message_finished,
1709
- error);
1584
+ exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_REF(error),
1585
+ "fetching_send_message_finished");
1586
+ while (s->on_write_finished_cbs) {
1587
+ grpc_chttp2_write_cb *cb = s->on_write_finished_cbs;
1588
+ s->on_write_finished_cbs = cb->next;
1589
+ grpc_chttp2_complete_closure_step(exec_ctx, t, s, &cb->closure,
1590
+ GRPC_ERROR_REF(error),
1591
+ "on_write_finished_cb");
1592
+ cb->next = t->write_cb_pool;
1593
+ t->write_cb_pool = cb;
1594
+ }
1595
+ GRPC_ERROR_UNREF(error);
1710
1596
  }
1711
1597
 
1712
- void grpc_chttp2_mark_stream_closed(
1713
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
1714
- grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
1715
- grpc_error *error) {
1716
- if (stream_global->read_closed && stream_global->write_closed) {
1598
+ void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
1599
+ grpc_chttp2_transport *t,
1600
+ grpc_chttp2_stream *s, int close_reads,
1601
+ int close_writes, grpc_error *error) {
1602
+ if (s->read_closed && s->write_closed) {
1717
1603
  /* already closed */
1718
1604
  GRPC_ERROR_UNREF(error);
1719
1605
  return;
1720
1606
  }
1721
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1722
- if (close_reads && !stream_global->read_closed) {
1723
- stream_global->read_closed_error = GRPC_ERROR_REF(error);
1724
- stream_global->read_closed = true;
1725
- stream_global->published_initial_metadata = true;
1726
- stream_global->published_trailing_metadata = true;
1727
- decrement_active_streams_locked(exec_ctx, transport_global, stream_global);
1728
- }
1729
- if (close_writes && !stream_global->write_closed) {
1730
- stream_global->write_closed_error = GRPC_ERROR_REF(error);
1731
- stream_global->write_closed = true;
1732
- if (TRANSPORT_FROM_GLOBAL(transport_global)->executor.write_state !=
1733
- GRPC_CHTTP2_WRITING_INACTIVE) {
1734
- GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes");
1735
- grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
1736
- stream_global);
1737
- } else {
1738
- fail_pending_writes(exec_ctx, transport_global, stream_global,
1739
- GRPC_ERROR_REF(error));
1607
+ if (close_reads && !s->read_closed) {
1608
+ s->read_closed_error = GRPC_ERROR_REF(error);
1609
+ s->read_closed = true;
1610
+ for (int i = 0; i < 2; i++) {
1611
+ if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) {
1612
+ s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE;
1613
+ }
1740
1614
  }
1741
- }
1742
- if (stream_global->read_closed && stream_global->write_closed) {
1743
- if (stream_global->id != 0 &&
1744
- TRANSPORT_FROM_GLOBAL(transport_global)->executor.parsing_active) {
1745
- grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
1746
- stream_global);
1615
+ decrement_active_streams_locked(exec_ctx, t, s);
1616
+ grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
1617
+ grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
1618
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1619
+ }
1620
+ if (close_writes && !s->write_closed) {
1621
+ s->write_closed_error = GRPC_ERROR_REF(error);
1622
+ s->write_closed = true;
1623
+ grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error));
1624
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1625
+ }
1626
+ if (s->read_closed && s->write_closed) {
1627
+ if (s->id != 0) {
1628
+ remove_stream(exec_ctx, t, s->id,
1629
+ removal_error(GRPC_ERROR_REF(error), s, "Stream removed"));
1747
1630
  } else {
1748
- if (stream_global->id != 0) {
1749
- remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
1750
- stream_global->id,
1751
- removal_error(GRPC_ERROR_REF(error), stream_global));
1752
- }
1753
- GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
1631
+ /* Purge streams waiting on concurrency still waiting for id assignment */
1632
+ grpc_chttp2_list_remove_waiting_for_concurrency(t, s);
1754
1633
  }
1634
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2");
1755
1635
  }
1756
1636
  GRPC_ERROR_UNREF(error);
1757
1637
  }
1758
1638
 
1759
- static void close_from_api(grpc_exec_ctx *exec_ctx,
1760
- grpc_chttp2_transport_global *transport_global,
1761
- grpc_chttp2_stream_global *stream_global,
1762
- grpc_error *error) {
1763
- gpr_slice hdr;
1764
- gpr_slice status_hdr;
1765
- gpr_slice message_pfx;
1639
+ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1640
+ grpc_chttp2_stream *s, grpc_error *error) {
1641
+ grpc_slice hdr;
1642
+ grpc_slice status_hdr;
1643
+ grpc_slice message_pfx;
1766
1644
  uint8_t *p;
1767
1645
  uint32_t len = 0;
1768
1646
  grpc_status_code grpc_status;
1769
1647
  grpc_chttp2_error_code http_error;
1770
- status_codes_from_error(error, stream_global->deadline, &http_error,
1771
- &grpc_status);
1648
+ status_codes_from_error(error, s->deadline, &http_error, &grpc_status);
1772
1649
 
1773
1650
  GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
1774
1651
 
1775
- if (stream_global->id != 0 && !transport_global->is_client) {
1652
+ if (s->id != 0 && !t->is_client) {
1776
1653
  /* Hand roll a header block.
1777
- This is unnecessarily ugly - at some point we should find a more elegant
1654
+ This is unnecessarily ugly - at some point we should find a more
1655
+ elegant
1778
1656
  solution.
1779
- It's complicated by the fact that our send machinery would be dead by the
1657
+ It's complicated by the fact that our send machinery would be dead by
1658
+ the
1780
1659
  time we got around to sending this, so instead we ignore HPACK
1781
1660
  compression
1782
1661
  and just write the uncompressed bytes onto the wire. */
1783
- status_hdr = gpr_slice_malloc(15 + (grpc_status >= 10));
1784
- p = GPR_SLICE_START_PTR(status_hdr);
1662
+ status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
1663
+ p = GRPC_SLICE_START_PTR(status_hdr);
1785
1664
  *p++ = 0x40; /* literal header */
1786
1665
  *p++ = 11; /* len(grpc-status) */
1787
1666
  *p++ = 'g';
@@ -1803,17 +1682,18 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1803
1682
  *p++ = (uint8_t)('0' + (grpc_status / 10));
1804
1683
  *p++ = (uint8_t)('0' + (grpc_status % 10));
1805
1684
  }
1806
- GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
1807
- len += (uint32_t)GPR_SLICE_LENGTH(status_hdr);
1685
+ GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
1686
+ len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
1808
1687
 
1809
1688
  const char *optional_message =
1810
1689
  grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
1811
1690
 
1812
1691
  if (optional_message != NULL) {
1813
1692
  size_t msg_len = strlen(optional_message);
1814
- GPR_ASSERT(msg_len < 127);
1815
- message_pfx = gpr_slice_malloc(15);
1816
- p = GPR_SLICE_START_PTR(message_pfx);
1693
+ GPR_ASSERT(msg_len <= UINT32_MAX);
1694
+ uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0);
1695
+ message_pfx = grpc_slice_malloc(14 + msg_len_len);
1696
+ p = GRPC_SLICE_START_PTR(message_pfx);
1817
1697
  *p++ = 0x40;
1818
1698
  *p++ = 12; /* len(grpc-message) */
1819
1699
  *p++ = 'g';
@@ -1828,36 +1708,37 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1828
1708
  *p++ = 'a';
1829
1709
  *p++ = 'g';
1830
1710
  *p++ = 'e';
1831
- *p++ = (uint8_t)msg_len;
1832
- GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
1833
- len += (uint32_t)GPR_SLICE_LENGTH(message_pfx);
1711
+ GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p,
1712
+ (uint32_t)msg_len_len);
1713
+ p += msg_len_len;
1714
+ GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
1715
+ len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
1834
1716
  len += (uint32_t)msg_len;
1835
1717
  }
1836
1718
 
1837
- hdr = gpr_slice_malloc(9);
1838
- p = GPR_SLICE_START_PTR(hdr);
1719
+ hdr = grpc_slice_malloc(9);
1720
+ p = GRPC_SLICE_START_PTR(hdr);
1839
1721
  *p++ = (uint8_t)(len >> 16);
1840
1722
  *p++ = (uint8_t)(len >> 8);
1841
1723
  *p++ = (uint8_t)(len);
1842
1724
  *p++ = GRPC_CHTTP2_FRAME_HEADER;
1843
1725
  *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
1844
- *p++ = (uint8_t)(stream_global->id >> 24);
1845
- *p++ = (uint8_t)(stream_global->id >> 16);
1846
- *p++ = (uint8_t)(stream_global->id >> 8);
1847
- *p++ = (uint8_t)(stream_global->id);
1848
- GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr));
1849
-
1850
- gpr_slice_buffer_add(&transport_global->qbuf, hdr);
1851
- gpr_slice_buffer_add(&transport_global->qbuf, status_hdr);
1726
+ *p++ = (uint8_t)(s->id >> 24);
1727
+ *p++ = (uint8_t)(s->id >> 16);
1728
+ *p++ = (uint8_t)(s->id >> 8);
1729
+ *p++ = (uint8_t)(s->id);
1730
+ GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
1731
+
1732
+ grpc_slice_buffer_add(&t->qbuf, hdr);
1733
+ grpc_slice_buffer_add(&t->qbuf, status_hdr);
1852
1734
  if (optional_message) {
1853
- gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
1854
- gpr_slice_buffer_add(&transport_global->qbuf,
1855
- gpr_slice_from_copied_string(optional_message));
1735
+ grpc_slice_buffer_add(&t->qbuf, message_pfx);
1736
+ grpc_slice_buffer_add(&t->qbuf,
1737
+ grpc_slice_from_copied_string(optional_message));
1856
1738
  }
1857
- gpr_slice_buffer_add(
1858
- &transport_global->qbuf,
1859
- grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR,
1860
- &stream_global->stats.outgoing));
1739
+ grpc_slice_buffer_add(
1740
+ &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR,
1741
+ &s->stats.outgoing));
1861
1742
  }
1862
1743
 
1863
1744
  const char *msg = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
@@ -1866,43 +1747,34 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1866
1747
  free_msg = true;
1867
1748
  msg = grpc_error_string(error);
1868
1749
  }
1869
- gpr_slice msg_slice = gpr_slice_from_copied_string(msg);
1870
- grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
1871
- grpc_status, &msg_slice);
1750
+ grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
1751
+ grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
1872
1752
  if (free_msg) grpc_error_free_string(msg);
1873
1753
 
1874
- grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1875
- 1, error);
1876
- grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
1877
- "close_from_api");
1754
+ grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error);
1755
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api");
1878
1756
  }
1879
1757
 
1880
1758
  typedef struct {
1881
1759
  grpc_exec_ctx *exec_ctx;
1882
1760
  grpc_error *error;
1761
+ grpc_chttp2_transport *t;
1883
1762
  } cancel_stream_cb_args;
1884
1763
 
1885
- static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
1886
- void *user_data,
1887
- grpc_chttp2_stream_global *stream_global) {
1764
+ static void cancel_stream_cb(void *user_data, uint32_t key, void *stream) {
1888
1765
  cancel_stream_cb_args *args = user_data;
1889
- cancel_from_api(args->exec_ctx, transport_global, stream_global,
1890
- GRPC_ERROR_REF(args->error));
1766
+ grpc_chttp2_stream *s = stream;
1767
+ grpc_chttp2_cancel_stream(args->exec_ctx, args->t, s,
1768
+ GRPC_ERROR_REF(args->error));
1891
1769
  }
1892
1770
 
1893
1771
  static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1894
1772
  grpc_error *error) {
1895
- cancel_stream_cb_args args = {exec_ctx, error};
1896
- grpc_chttp2_for_all_streams(&t->global, &args, cancel_stream_cb);
1773
+ cancel_stream_cb_args args = {exec_ctx, error, t};
1774
+ grpc_chttp2_stream_map_for_each(&t->stream_map, cancel_stream_cb, &args);
1897
1775
  GRPC_ERROR_UNREF(error);
1898
1776
  }
1899
1777
 
1900
- static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1901
- grpc_error *error) {
1902
- close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
1903
- end_all_the_calls(exec_ctx, t, error);
1904
- }
1905
-
1906
1778
  /** update window from a settings change */
1907
1779
  typedef struct {
1908
1780
  grpc_chttp2_transport *t;
@@ -1913,20 +1785,23 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
1913
1785
  update_global_window_args *a = args;
1914
1786
  grpc_chttp2_transport *t = a->t;
1915
1787
  grpc_chttp2_stream *s = stream;
1916
- grpc_chttp2_transport_global *transport_global = &t->global;
1917
- grpc_chttp2_stream_global *stream_global = &s->global;
1918
1788
  int was_zero;
1919
1789
  int is_zero;
1920
- int64_t initial_window_update = t->parsing.initial_window_update;
1790
+ int64_t initial_window_update = t->initial_window_update;
1921
1791
 
1922
- was_zero = stream_global->outgoing_window <= 0;
1923
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", transport_global, stream_global,
1924
- outgoing_window, initial_window_update);
1925
- is_zero = stream_global->outgoing_window <= 0;
1792
+ if (initial_window_update > 0) {
1793
+ was_zero = s->outgoing_window <= 0;
1794
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", t, s, outgoing_window,
1795
+ initial_window_update);
1796
+ is_zero = s->outgoing_window <= 0;
1926
1797
 
1927
- if (was_zero && !is_zero) {
1928
- grpc_chttp2_become_writable(a->exec_ctx, transport_global, stream_global,
1929
- true, "update_global_window");
1798
+ if (was_zero && !is_zero) {
1799
+ grpc_chttp2_become_writable(a->exec_ctx, t, s, true,
1800
+ "update_global_window");
1801
+ }
1802
+ } else {
1803
+ GRPC_CHTTP2_FLOW_DEBIT_STREAM("settings", t, s, outgoing_window,
1804
+ -initial_window_update);
1930
1805
  }
1931
1806
  }
1932
1807
 
@@ -1934,47 +1809,6 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
1934
1809
  * INPUT PROCESSING - PARSING
1935
1810
  */
1936
1811
 
1937
- static void reading_action_locked(grpc_exec_ctx *exec_ctx,
1938
- grpc_chttp2_transport *t,
1939
- grpc_chttp2_stream *s_unused, void *arg);
1940
- static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
1941
- grpc_error *error);
1942
- static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1943
- grpc_chttp2_transport *t,
1944
- grpc_chttp2_stream *s_unused, void *arg);
1945
- static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1946
- grpc_chttp2_stream *s_unused, void *arg);
1947
-
1948
- static void reading_action(grpc_exec_ctx *exec_ctx, void *tp,
1949
- grpc_error *error) {
1950
- /* Control flow:
1951
- reading_action_locked ->
1952
- (parse_unlocked -> post_parse_locked)? ->
1953
- post_reading_action_locked */
1954
- grpc_chttp2_run_with_global_lock(exec_ctx, tp, NULL, reading_action_locked,
1955
- GRPC_ERROR_REF(error), 0);
1956
- }
1957
-
1958
- static void reading_action_locked(grpc_exec_ctx *exec_ctx,
1959
- grpc_chttp2_transport *t,
1960
- grpc_chttp2_stream *s_unused, void *arg) {
1961
- grpc_chttp2_transport_global *transport_global = &t->global;
1962
- grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
1963
- grpc_error *error = arg;
1964
-
1965
- GPR_ASSERT(!t->executor.parsing_active);
1966
- if (!t->closed) {
1967
- t->executor.parsing_active = 1;
1968
- /* merge stream lists */
1969
- grpc_chttp2_stream_map_move_into(&t->new_stream_map,
1970
- &t->parsing_stream_map);
1971
- grpc_chttp2_prepare_to_read(transport_global, transport_parsing);
1972
- grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL);
1973
- } else {
1974
- post_reading_action_locked(exec_ctx, t, s_unused, arg);
1975
- }
1976
- }
1977
-
1978
1812
  static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
1979
1813
  grpc_chttp2_transport *t) {
1980
1814
  grpc_http_parser parser;
@@ -1987,7 +1821,8 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
1987
1821
 
1988
1822
  grpc_error *parse_error = GRPC_ERROR_NONE;
1989
1823
  for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) {
1990
- parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i]);
1824
+ parse_error =
1825
+ grpc_http_parser_parse(&parser, t->read_buffer.slices[i], NULL);
1991
1826
  }
1992
1827
  if (parse_error == GRPC_ERROR_NONE &&
1993
1828
  (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
@@ -2002,169 +1837,119 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
2002
1837
  return error;
2003
1838
  }
2004
1839
 
2005
- static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
2006
- grpc_error *error) {
2007
- grpc_chttp2_transport *t = arg;
2008
- grpc_error *err = GRPC_ERROR_NONE;
2009
- GPR_TIMER_BEGIN("reading_action.parse", 0);
2010
- size_t i = 0;
2011
- grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
2012
- GRPC_ERROR_NONE};
2013
- for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
2014
- errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing,
2015
- t->read_buffer.slices[i]);
2016
- };
2017
- if (errors[1] == GRPC_ERROR_NONE) {
2018
- err = GRPC_ERROR_REF(error);
2019
- } else {
2020
- errors[2] = try_http_parsing(exec_ctx, t);
2021
- err = GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
2022
- GPR_ARRAY_SIZE(errors));
2023
- }
2024
- for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
2025
- GRPC_ERROR_UNREF(errors[i]);
2026
- }
2027
- GPR_TIMER_END("reading_action.parse", 0);
2028
- grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, err,
2029
- 0);
2030
- }
2031
-
2032
- static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
2033
- grpc_chttp2_stream *s_unused, void *arg) {
2034
- grpc_chttp2_transport_global *transport_global = &t->global;
2035
- grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
2036
- /* copy parsing qbuf to global qbuf */
2037
- if (t->parsing.qbuf.count > 0) {
2038
- gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf);
2039
- grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
2040
- "parsing_qbuf");
2041
- }
2042
- /* merge stream lists */
2043
- grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map);
2044
- transport_global->concurrent_stream_count =
2045
- (uint32_t)grpc_chttp2_stream_map_size(&t->parsing_stream_map);
2046
- if (transport_parsing->initial_window_update != 0) {
2047
- update_global_window_args args = {t, exec_ctx};
2048
- grpc_chttp2_stream_map_for_each(&t->parsing_stream_map,
2049
- update_global_window, &args);
2050
- transport_parsing->initial_window_update = 0;
2051
- }
2052
- /* handle higher level things */
2053
- grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing);
2054
- t->executor.parsing_active = 0;
2055
- /* handle delayed transport ops (if there is one) */
2056
- if (t->post_parsing_op) {
2057
- grpc_transport_op *op = t->post_parsing_op;
2058
- t->post_parsing_op = NULL;
2059
- perform_transport_op_locked(exec_ctx, t, NULL, op);
2060
- gpr_free(op);
2061
- }
2062
- /* if a stream is in the stream map, and gets cancelled, we need to
2063
- * ensure we are not parsing before continuing the cancellation to keep
2064
- * things in a sane state */
2065
- grpc_chttp2_stream_global *stream_global;
2066
- while (grpc_chttp2_list_pop_closed_waiting_for_parsing(transport_global,
2067
- &stream_global)) {
2068
- GPR_ASSERT(stream_global->in_stream_map);
2069
- GPR_ASSERT(stream_global->write_closed);
2070
- GPR_ASSERT(stream_global->read_closed);
2071
- remove_stream(exec_ctx, t, stream_global->id,
2072
- removal_error(GRPC_ERROR_NONE, stream_global));
2073
- GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
2074
- }
2075
-
2076
- post_reading_action_locked(exec_ctx, t, s_unused, arg);
2077
- }
2078
-
2079
- static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
2080
- grpc_chttp2_transport *t,
2081
- grpc_chttp2_stream *s_unused,
2082
- void *arg) {
2083
- grpc_error *error = arg;
1840
+ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
1841
+ grpc_error *error) {
1842
+ GPR_TIMER_BEGIN("reading_action_locked", 0);
1843
+
1844
+ grpc_chttp2_transport *t = tp;
1845
+
1846
+ GRPC_ERROR_REF(error);
1847
+
1848
+ grpc_error *err = error;
1849
+ if (err != GRPC_ERROR_NONE) {
1850
+ err = grpc_error_set_int(
1851
+ GRPC_ERROR_CREATE_REFERENCING("Endpoint read failed", &err, 1),
1852
+ GRPC_ERROR_INT_OCCURRED_DURING_WRITE, t->write_state);
1853
+ }
1854
+ GPR_SWAP(grpc_error *, err, error);
1855
+ GRPC_ERROR_UNREF(err);
1856
+ if (!t->closed) {
1857
+ GPR_TIMER_BEGIN("reading_action.parse", 0);
1858
+ size_t i = 0;
1859
+ grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
1860
+ GRPC_ERROR_NONE};
1861
+ for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
1862
+ errors[1] =
1863
+ grpc_chttp2_perform_read(exec_ctx, t, t->read_buffer.slices[i]);
1864
+ };
1865
+ if (errors[1] != GRPC_ERROR_NONE) {
1866
+ errors[2] = try_http_parsing(exec_ctx, t);
1867
+ GRPC_ERROR_UNREF(error);
1868
+ error = GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
1869
+ GPR_ARRAY_SIZE(errors));
1870
+ }
1871
+ for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
1872
+ GRPC_ERROR_UNREF(errors[i]);
1873
+ }
1874
+ GPR_TIMER_END("reading_action.parse", 0);
1875
+
1876
+ GPR_TIMER_BEGIN("post_parse_locked", 0);
1877
+ if (t->initial_window_update != 0) {
1878
+ update_global_window_args args = {t, exec_ctx};
1879
+ grpc_chttp2_stream_map_for_each(&t->stream_map, update_global_window,
1880
+ &args);
1881
+ t->initial_window_update = 0;
1882
+ }
1883
+ /* handle higher level things */
1884
+ if (t->incoming_window < t->connection_window_target * 3 / 4) {
1885
+ int64_t announce_bytes = t->connection_window_target - t->incoming_window;
1886
+ GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, announce_incoming_window,
1887
+ announce_bytes);
1888
+ GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, incoming_window,
1889
+ announce_bytes);
1890
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "global incoming window");
1891
+ }
1892
+
1893
+ GPR_TIMER_END("post_parse_locked", 0);
1894
+ }
1895
+
1896
+ GPR_TIMER_BEGIN("post_reading_action_locked", 0);
2084
1897
  bool keep_reading = false;
2085
1898
  if (error == GRPC_ERROR_NONE && t->closed) {
2086
1899
  error = GRPC_ERROR_CREATE("Transport closed");
2087
1900
  }
2088
1901
  if (error != GRPC_ERROR_NONE) {
2089
- if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) {
2090
- error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
2091
- GRPC_STATUS_UNAVAILABLE);
2092
- }
2093
- drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
1902
+ close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
2094
1903
  t->endpoint_reading = 0;
2095
- if (grpc_http_write_state_trace) {
2096
- gpr_log(GPR_DEBUG, "R:%p -> 0 ws=%s", t,
2097
- write_state_name(t->executor.write_state));
2098
- }
2099
- if (t->executor.write_state == GRPC_CHTTP2_WRITING_INACTIVE && t->ep) {
2100
- destroy_endpoint(exec_ctx, t);
2101
- }
2102
1904
  } else if (!t->closed) {
2103
1905
  keep_reading = true;
2104
- REF_TRANSPORT(t, "keep_reading");
2105
- prevent_endpoint_shutdown(t);
1906
+ GRPC_CHTTP2_REF_TRANSPORT(t, "keep_reading");
2106
1907
  }
2107
- gpr_slice_buffer_reset_and_unref(&t->read_buffer);
2108
- GRPC_ERROR_UNREF(error);
1908
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &t->read_buffer);
2109
1909
 
2110
1910
  if (keep_reading) {
2111
- grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->reading_action);
2112
- allow_endpoint_shutdown_locked(exec_ctx, t);
2113
- UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
1911
+ grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer,
1912
+ &t->read_action_locked);
1913
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
2114
1914
  } else {
2115
- UNREF_TRANSPORT(exec_ctx, t, "reading_action");
1915
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "reading_action");
2116
1916
  }
1917
+
1918
+ GPR_TIMER_END("post_reading_action_locked", 0);
1919
+
1920
+ GRPC_ERROR_UNREF(error);
1921
+
1922
+ GPR_TIMER_END("reading_action_locked", 0);
2117
1923
  }
2118
1924
 
2119
1925
  /*******************************************************************************
2120
1926
  * CALLBACK LOOP
2121
1927
  */
2122
1928
 
2123
- static void connectivity_state_set(
2124
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
2125
- grpc_connectivity_state state, grpc_error *error, const char *reason) {
1929
+ static void connectivity_state_set(grpc_exec_ctx *exec_ctx,
1930
+ grpc_chttp2_transport *t,
1931
+ grpc_connectivity_state state,
1932
+ grpc_error *error, const char *reason) {
2126
1933
  GRPC_CHTTP2_IF_TRACING(
2127
1934
  gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
2128
- grpc_connectivity_state_set(
2129
- exec_ctx,
2130
- &TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker,
2131
- state, error, reason);
1935
+ grpc_connectivity_state_set(exec_ctx, &t->channel_callback.state_tracker,
1936
+ state, error, reason);
2132
1937
  }
2133
1938
 
2134
1939
  /*******************************************************************************
2135
1940
  * POLLSET STUFF
2136
1941
  */
2137
1942
 
2138
- static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
2139
- grpc_chttp2_transport *t,
2140
- grpc_chttp2_stream *s_unused, void *pollset) {
2141
- if (t->ep) {
2142
- grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset);
2143
- }
2144
- }
2145
-
2146
- static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
2147
- grpc_chttp2_transport *t,
2148
- grpc_chttp2_stream *s_unused,
2149
- void *pollset_set) {
2150
- if (t->ep) {
2151
- grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set);
2152
- }
2153
- }
2154
-
2155
1943
  static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
2156
1944
  grpc_stream *gs, grpc_pollset *pollset) {
2157
- /* TODO(ctiller): keep pollset alive */
2158
- grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt,
2159
- (grpc_chttp2_stream *)gs,
2160
- add_to_pollset_locked, pollset, 0);
1945
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
1946
+ grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset);
2161
1947
  }
2162
1948
 
2163
1949
  static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
2164
1950
  grpc_stream *gs, grpc_pollset_set *pollset_set) {
2165
- grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt,
2166
- (grpc_chttp2_stream *)gs,
2167
- add_to_pollset_set_locked, pollset_set, 0);
1951
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
1952
+ grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set);
2168
1953
  }
2169
1954
 
2170
1955
  /*******************************************************************************
@@ -2175,20 +1960,22 @@ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
2175
1960
  grpc_chttp2_incoming_byte_stream *bs) {
2176
1961
  if (gpr_unref(&bs->refs)) {
2177
1962
  GRPC_ERROR_UNREF(bs->error);
2178
- gpr_slice_buffer_destroy(&bs->slices);
1963
+ grpc_slice_buffer_destroy_internal(exec_ctx, &bs->slices);
1964
+ gpr_mu_destroy(&bs->slice_mu);
2179
1965
  gpr_free(bs);
2180
1966
  }
2181
1967
  }
2182
1968
 
2183
- static void incoming_byte_stream_update_flow_control(
2184
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
2185
- grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
2186
- size_t have_already) {
1969
+ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
1970
+ grpc_chttp2_transport *t,
1971
+ grpc_chttp2_stream *s,
1972
+ size_t max_size_hint,
1973
+ size_t have_already) {
2187
1974
  uint32_t max_recv_bytes;
2188
1975
 
2189
1976
  /* clamp max recv hint to an allowable size */
2190
- if (max_size_hint >= UINT32_MAX - transport_global->stream_lookahead) {
2191
- max_recv_bytes = UINT32_MAX - transport_global->stream_lookahead;
1977
+ if (max_size_hint >= UINT32_MAX - t->stream_lookahead) {
1978
+ max_recv_bytes = UINT32_MAX - t->stream_lookahead;
2192
1979
  } else {
2193
1980
  max_recv_bytes = (uint32_t)max_size_hint;
2194
1981
  }
@@ -2201,72 +1988,71 @@ static void incoming_byte_stream_update_flow_control(
2201
1988
  }
2202
1989
 
2203
1990
  /* add some small lookahead to keep pipelines flowing */
2204
- GPR_ASSERT(max_recv_bytes <= UINT32_MAX - transport_global->stream_lookahead);
2205
- max_recv_bytes += transport_global->stream_lookahead;
2206
- if (stream_global->max_recv_bytes < max_recv_bytes) {
2207
- uint32_t add_max_recv_bytes =
2208
- max_recv_bytes - stream_global->max_recv_bytes;
2209
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
2210
- max_recv_bytes, add_max_recv_bytes);
2211
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
2212
- unannounced_incoming_window_for_parse,
1991
+ GPR_ASSERT(max_recv_bytes <= UINT32_MAX - t->stream_lookahead);
1992
+ max_recv_bytes += t->stream_lookahead;
1993
+ if (s->max_recv_bytes < max_recv_bytes) {
1994
+ uint32_t add_max_recv_bytes = max_recv_bytes - s->max_recv_bytes;
1995
+ bool new_window_write_is_covered_by_poller =
1996
+ s->max_recv_bytes < have_already;
1997
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, max_recv_bytes,
1998
+ add_max_recv_bytes);
1999
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window,
2213
2000
  add_max_recv_bytes);
2214
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
2215
- unannounced_incoming_window_for_writing,
2001
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window,
2216
2002
  add_max_recv_bytes);
2217
- grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
2218
- stream_global);
2219
- grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
2220
- false, "read_incoming_stream");
2003
+ grpc_chttp2_become_writable(exec_ctx, t, s,
2004
+ new_window_write_is_covered_by_poller,
2005
+ "read_incoming_stream");
2221
2006
  }
2222
2007
  }
2223
2008
 
2224
- typedef struct {
2225
- grpc_chttp2_incoming_byte_stream *byte_stream;
2226
- gpr_slice *slice;
2227
- size_t max_size_hint;
2228
- grpc_closure *on_complete;
2229
- } incoming_byte_stream_next_arg;
2230
-
2231
2009
  static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx,
2232
- grpc_chttp2_transport *t,
2233
- grpc_chttp2_stream *s,
2234
- void *argp) {
2235
- incoming_byte_stream_next_arg *arg = argp;
2236
- grpc_chttp2_incoming_byte_stream *bs =
2237
- (grpc_chttp2_incoming_byte_stream *)arg->byte_stream;
2238
- grpc_chttp2_transport_global *transport_global = &bs->transport->global;
2239
- grpc_chttp2_stream_global *stream_global = &bs->stream->global;
2010
+ void *argp,
2011
+ grpc_error *error_ignored) {
2012
+ grpc_chttp2_incoming_byte_stream *bs = argp;
2013
+ grpc_chttp2_transport *t = bs->transport;
2014
+ grpc_chttp2_stream *s = bs->stream;
2240
2015
 
2241
2016
  if (bs->is_tail) {
2242
- incoming_byte_stream_update_flow_control(exec_ctx, transport_global,
2243
- stream_global, arg->max_size_hint,
2244
- bs->slices.length);
2017
+ gpr_mu_lock(&bs->slice_mu);
2018
+ size_t cur_length = bs->slices.length;
2019
+ gpr_mu_unlock(&bs->slice_mu);
2020
+ incoming_byte_stream_update_flow_control(
2021
+ exec_ctx, t, s, bs->next_action.max_size_hint, cur_length);
2245
2022
  }
2023
+ gpr_mu_lock(&bs->slice_mu);
2246
2024
  if (bs->slices.count > 0) {
2247
- *arg->slice = gpr_slice_buffer_take_first(&bs->slices);
2248
- grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_NONE, NULL);
2025
+ *bs->next_action.slice = grpc_slice_buffer_take_first(&bs->slices);
2026
+ grpc_closure_run(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE);
2249
2027
  } else if (bs->error != GRPC_ERROR_NONE) {
2250
- grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_REF(bs->error),
2251
- NULL);
2028
+ grpc_closure_run(exec_ctx, bs->next_action.on_complete,
2029
+ GRPC_ERROR_REF(bs->error));
2252
2030
  } else {
2253
- bs->on_next = arg->on_complete;
2254
- bs->next = arg->slice;
2031
+ bs->on_next = bs->next_action.on_complete;
2032
+ bs->next = bs->next_action.slice;
2255
2033
  }
2034
+ gpr_mu_unlock(&bs->slice_mu);
2256
2035
  incoming_byte_stream_unref(exec_ctx, bs);
2257
2036
  }
2258
2037
 
2259
2038
  static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx,
2260
2039
  grpc_byte_stream *byte_stream,
2261
- gpr_slice *slice, size_t max_size_hint,
2040
+ grpc_slice *slice, size_t max_size_hint,
2262
2041
  grpc_closure *on_complete) {
2042
+ GPR_TIMER_BEGIN("incoming_byte_stream_next", 0);
2263
2043
  grpc_chttp2_incoming_byte_stream *bs =
2264
2044
  (grpc_chttp2_incoming_byte_stream *)byte_stream;
2265
- incoming_byte_stream_next_arg arg = {bs, slice, max_size_hint, on_complete};
2266
2045
  gpr_ref(&bs->refs);
2267
- grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream,
2268
- incoming_byte_stream_next_locked, &arg,
2269
- sizeof(arg));
2046
+ bs->next_action.slice = slice;
2047
+ bs->next_action.max_size_hint = max_size_hint;
2048
+ bs->next_action.on_complete = on_complete;
2049
+ grpc_closure_sched(
2050
+ exec_ctx,
2051
+ grpc_closure_init(
2052
+ &bs->next_action.closure, incoming_byte_stream_next_locked, bs,
2053
+ grpc_combiner_scheduler(bs->transport->combiner, false)),
2054
+ GRPC_ERROR_NONE);
2055
+ GPR_TIMER_END("incoming_byte_stream_next", 0);
2270
2056
  return 0;
2271
2057
  }
2272
2058
 
@@ -2274,183 +2060,218 @@ static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
2274
2060
  grpc_byte_stream *byte_stream);
2275
2061
 
2276
2062
  static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
2277
- grpc_chttp2_transport *t,
2278
- grpc_chttp2_stream *s,
2279
- void *byte_stream) {
2063
+ void *byte_stream,
2064
+ grpc_error *error_ignored) {
2280
2065
  grpc_chttp2_incoming_byte_stream *bs = byte_stream;
2281
2066
  GPR_ASSERT(bs->base.destroy == incoming_byte_stream_destroy);
2282
- decrement_active_streams_locked(exec_ctx, &bs->transport->global,
2283
- &bs->stream->global);
2067
+ decrement_active_streams_locked(exec_ctx, bs->transport, bs->stream);
2284
2068
  incoming_byte_stream_unref(exec_ctx, bs);
2285
2069
  }
2286
2070
 
2287
2071
  static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
2288
2072
  grpc_byte_stream *byte_stream) {
2073
+ GPR_TIMER_BEGIN("incoming_byte_stream_destroy", 0);
2289
2074
  grpc_chttp2_incoming_byte_stream *bs =
2290
2075
  (grpc_chttp2_incoming_byte_stream *)byte_stream;
2291
- grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream,
2292
- incoming_byte_stream_destroy_locked, bs, 0);
2293
- }
2294
-
2295
- typedef struct {
2296
- grpc_chttp2_incoming_byte_stream *byte_stream;
2297
- gpr_slice slice;
2298
- } incoming_byte_stream_push_arg;
2299
-
2300
- static void incoming_byte_stream_push_locked(grpc_exec_ctx *exec_ctx,
2301
- grpc_chttp2_transport *t,
2302
- grpc_chttp2_stream *s,
2303
- void *argp) {
2304
- incoming_byte_stream_push_arg *arg = argp;
2305
- grpc_chttp2_incoming_byte_stream *bs = arg->byte_stream;
2306
- if (bs->on_next != NULL) {
2307
- *bs->next = arg->slice;
2308
- grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE, NULL);
2309
- bs->on_next = NULL;
2310
- } else {
2311
- gpr_slice_buffer_add(&bs->slices, arg->slice);
2312
- }
2313
- incoming_byte_stream_unref(exec_ctx, bs);
2314
- }
2315
-
2316
- void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
2317
- grpc_chttp2_incoming_byte_stream *bs,
2318
- gpr_slice slice) {
2319
- incoming_byte_stream_push_arg arg = {bs, slice};
2320
- gpr_ref(&bs->refs);
2321
- grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream,
2322
- incoming_byte_stream_push_locked, &arg,
2323
- sizeof(arg));
2324
- }
2325
-
2326
- typedef struct {
2327
- grpc_chttp2_incoming_byte_stream *bs;
2328
- grpc_error *error;
2329
- } bs_fail_args;
2330
-
2331
- static bs_fail_args *make_bs_fail_args(grpc_chttp2_incoming_byte_stream *bs,
2332
- grpc_error *error) {
2333
- bs_fail_args *a = gpr_malloc(sizeof(*a));
2334
- a->bs = bs;
2335
- a->error = error;
2336
- return a;
2076
+ grpc_closure_sched(
2077
+ exec_ctx,
2078
+ grpc_closure_init(
2079
+ &bs->destroy_action, incoming_byte_stream_destroy_locked, bs,
2080
+ grpc_combiner_scheduler(bs->transport->combiner, false)),
2081
+ GRPC_ERROR_NONE);
2082
+ GPR_TIMER_END("incoming_byte_stream_destroy", 0);
2337
2083
  }
2338
2084
 
2339
- static void incoming_byte_stream_finished_failed_locked(
2340
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
2341
- void *argp) {
2342
- bs_fail_args *a = argp;
2343
- grpc_chttp2_incoming_byte_stream *bs = a->bs;
2344
- grpc_error *error = a->error;
2345
- gpr_free(a);
2346
- grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL);
2085
+ static void incoming_byte_stream_publish_error(
2086
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
2087
+ grpc_error *error) {
2088
+ GPR_ASSERT(error != GRPC_ERROR_NONE);
2089
+ grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error));
2347
2090
  bs->on_next = NULL;
2348
2091
  GRPC_ERROR_UNREF(bs->error);
2349
2092
  bs->error = error;
2350
- incoming_byte_stream_unref(exec_ctx, bs);
2351
2093
  }
2352
2094
 
2353
- static void incoming_byte_stream_finished_ok_locked(grpc_exec_ctx *exec_ctx,
2354
- grpc_chttp2_transport *t,
2355
- grpc_chttp2_stream *s,
2356
- void *argp) {
2357
- grpc_chttp2_incoming_byte_stream *bs = argp;
2358
- incoming_byte_stream_unref(exec_ctx, bs);
2095
+ void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
2096
+ grpc_chttp2_incoming_byte_stream *bs,
2097
+ grpc_slice slice) {
2098
+ gpr_mu_lock(&bs->slice_mu);
2099
+ if (bs->remaining_bytes < GRPC_SLICE_LENGTH(slice)) {
2100
+ incoming_byte_stream_publish_error(
2101
+ exec_ctx, bs, GRPC_ERROR_CREATE("Too many bytes in stream"));
2102
+ } else {
2103
+ bs->remaining_bytes -= (uint32_t)GRPC_SLICE_LENGTH(slice);
2104
+ if (bs->on_next != NULL) {
2105
+ *bs->next = slice;
2106
+ grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE);
2107
+ bs->on_next = NULL;
2108
+ } else {
2109
+ grpc_slice_buffer_add(&bs->slices, slice);
2110
+ }
2111
+ }
2112
+ gpr_mu_unlock(&bs->slice_mu);
2359
2113
  }
2360
2114
 
2361
2115
  void grpc_chttp2_incoming_byte_stream_finished(
2362
2116
  grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
2363
- grpc_error *error, int from_parsing_thread) {
2364
- if (from_parsing_thread) {
2365
- if (error == GRPC_ERROR_NONE) {
2366
- grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream,
2367
- incoming_byte_stream_finished_ok_locked,
2368
- bs, 0);
2369
- } else {
2370
- grpc_chttp2_run_with_global_lock(
2371
- exec_ctx, bs->transport, bs->stream,
2372
- incoming_byte_stream_finished_failed_locked,
2373
- make_bs_fail_args(bs, error), 0);
2374
- }
2375
- } else {
2376
- if (error == GRPC_ERROR_NONE) {
2377
- incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport,
2378
- bs->stream, bs);
2379
- } else {
2380
- incoming_byte_stream_finished_failed_locked(
2381
- exec_ctx, bs->transport, bs->stream, make_bs_fail_args(bs, error));
2117
+ grpc_error *error) {
2118
+ if (error == GRPC_ERROR_NONE) {
2119
+ gpr_mu_lock(&bs->slice_mu);
2120
+ if (bs->remaining_bytes != 0) {
2121
+ error = GRPC_ERROR_CREATE("Truncated message");
2382
2122
  }
2123
+ gpr_mu_unlock(&bs->slice_mu);
2383
2124
  }
2125
+ if (error != GRPC_ERROR_NONE) {
2126
+ incoming_byte_stream_publish_error(exec_ctx, bs, error);
2127
+ }
2128
+ incoming_byte_stream_unref(exec_ctx, bs);
2384
2129
  }
2385
2130
 
2386
2131
  grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
2387
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
2388
- grpc_chttp2_stream_parsing *stream_parsing, uint32_t frame_size,
2389
- uint32_t flags, grpc_chttp2_incoming_frame_queue *add_to_queue) {
2132
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
2133
+ uint32_t frame_size, uint32_t flags) {
2390
2134
  grpc_chttp2_incoming_byte_stream *incoming_byte_stream =
2391
2135
  gpr_malloc(sizeof(*incoming_byte_stream));
2392
2136
  incoming_byte_stream->base.length = frame_size;
2137
+ incoming_byte_stream->remaining_bytes = frame_size;
2393
2138
  incoming_byte_stream->base.flags = flags;
2394
2139
  incoming_byte_stream->base.next = incoming_byte_stream_next;
2395
2140
  incoming_byte_stream->base.destroy = incoming_byte_stream_destroy;
2141
+ gpr_mu_init(&incoming_byte_stream->slice_mu);
2396
2142
  gpr_ref_init(&incoming_byte_stream->refs, 2);
2397
2143
  incoming_byte_stream->next_message = NULL;
2398
- incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing);
2399
- incoming_byte_stream->stream = STREAM_FROM_PARSING(stream_parsing);
2400
- gpr_ref(&incoming_byte_stream->stream->global.active_streams);
2401
- gpr_slice_buffer_init(&incoming_byte_stream->slices);
2144
+ incoming_byte_stream->transport = t;
2145
+ incoming_byte_stream->stream = s;
2146
+ gpr_ref(&incoming_byte_stream->stream->active_streams);
2147
+ grpc_slice_buffer_init(&incoming_byte_stream->slices);
2402
2148
  incoming_byte_stream->on_next = NULL;
2403
2149
  incoming_byte_stream->is_tail = 1;
2404
2150
  incoming_byte_stream->error = GRPC_ERROR_NONE;
2405
- if (add_to_queue->head == NULL) {
2406
- add_to_queue->head = incoming_byte_stream;
2151
+ grpc_chttp2_incoming_frame_queue *q = &s->incoming_frames;
2152
+ if (q->head == NULL) {
2153
+ q->head = incoming_byte_stream;
2407
2154
  } else {
2408
- add_to_queue->tail->is_tail = 0;
2409
- add_to_queue->tail->next_message = incoming_byte_stream;
2155
+ q->tail->is_tail = 0;
2156
+ q->tail->next_message = incoming_byte_stream;
2410
2157
  }
2411
- add_to_queue->tail = incoming_byte_stream;
2158
+ q->tail = incoming_byte_stream;
2159
+ grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
2412
2160
  return incoming_byte_stream;
2413
2161
  }
2414
2162
 
2415
2163
  /*******************************************************************************
2416
- * TRACING
2164
+ * RESOURCE QUOTAS
2417
2165
  */
2418
2166
 
2419
- static char *format_flowctl_context_var(const char *context, const char *var,
2420
- int64_t val, uint32_t id,
2421
- char **scope) {
2422
- char *underscore_pos;
2423
- char *buf;
2424
- char *result;
2425
- if (context == NULL) {
2426
- *scope = NULL;
2427
- gpr_asprintf(&buf, "%s(%" PRId64 ")", var, val);
2428
- result = gpr_leftpad(buf, ' ', 60);
2429
- gpr_free(buf);
2430
- return result;
2431
- }
2432
- underscore_pos = strchr(context, '_');
2433
- *scope = gpr_strdup(context);
2434
- (*scope)[underscore_pos - context] = 0;
2435
- if (id != 0) {
2436
- char *tmp = *scope;
2437
- gpr_asprintf(scope, "%s[%d]", tmp, id);
2438
- gpr_free(tmp);
2439
- }
2440
- gpr_asprintf(&buf, "%s.%s(%" PRId64 ")", underscore_pos + 1, var, val);
2441
- result = gpr_leftpad(buf, ' ', 60);
2442
- gpr_free(buf);
2443
- return result;
2167
+ static void post_benign_reclaimer(grpc_exec_ctx *exec_ctx,
2168
+ grpc_chttp2_transport *t) {
2169
+ if (!t->benign_reclaimer_registered) {
2170
+ t->benign_reclaimer_registered = true;
2171
+ GRPC_CHTTP2_REF_TRANSPORT(t, "benign_reclaimer");
2172
+ grpc_resource_user_post_reclaimer(exec_ctx,
2173
+ grpc_endpoint_get_resource_user(t->ep),
2174
+ false, &t->benign_reclaimer_locked);
2175
+ }
2176
+ }
2177
+
2178
+ static void post_destructive_reclaimer(grpc_exec_ctx *exec_ctx,
2179
+ grpc_chttp2_transport *t) {
2180
+ if (!t->destructive_reclaimer_registered) {
2181
+ t->destructive_reclaimer_registered = true;
2182
+ GRPC_CHTTP2_REF_TRANSPORT(t, "destructive_reclaimer");
2183
+ grpc_resource_user_post_reclaimer(exec_ctx,
2184
+ grpc_endpoint_get_resource_user(t->ep),
2185
+ true, &t->destructive_reclaimer_locked);
2186
+ }
2187
+ }
2188
+
2189
+ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2190
+ grpc_error *error) {
2191
+ grpc_chttp2_transport *t = arg;
2192
+ if (error == GRPC_ERROR_NONE &&
2193
+ grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
2194
+ /* Channel with no active streams: send a goaway to try and make it
2195
+ * disconnect cleanly */
2196
+ if (grpc_resource_quota_trace) {
2197
+ gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory",
2198
+ t->peer_string);
2199
+ }
2200
+ send_goaway(exec_ctx, t, GRPC_CHTTP2_ENHANCE_YOUR_CALM,
2201
+ grpc_slice_from_static_string("Buffers full"));
2202
+ } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) {
2203
+ gpr_log(GPR_DEBUG,
2204
+ "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
2205
+ " streams",
2206
+ t->peer_string, grpc_chttp2_stream_map_size(&t->stream_map));
2207
+ }
2208
+ t->benign_reclaimer_registered = false;
2209
+ if (error != GRPC_ERROR_CANCELLED) {
2210
+ grpc_resource_user_finish_reclamation(
2211
+ exec_ctx, grpc_endpoint_get_resource_user(t->ep));
2212
+ }
2213
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "benign_reclaimer");
2444
2214
  }
2445
2215
 
2446
- static int samestr(char *a, char *b) {
2447
- if (a == NULL) {
2448
- return b == NULL;
2216
+ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2217
+ grpc_error *error) {
2218
+ grpc_chttp2_transport *t = arg;
2219
+ size_t n = grpc_chttp2_stream_map_size(&t->stream_map);
2220
+ t->destructive_reclaimer_registered = false;
2221
+ if (error == GRPC_ERROR_NONE && n > 0) {
2222
+ grpc_chttp2_stream *s = grpc_chttp2_stream_map_rand(&t->stream_map);
2223
+ if (grpc_resource_quota_trace) {
2224
+ gpr_log(GPR_DEBUG, "HTTP2: %s - abandon stream id %d", t->peer_string,
2225
+ s->id);
2226
+ }
2227
+ grpc_chttp2_cancel_stream(
2228
+ exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
2229
+ GRPC_ERROR_INT_HTTP2_ERROR,
2230
+ GRPC_CHTTP2_ENHANCE_YOUR_CALM));
2231
+ if (n > 1) {
2232
+ /* Since we cancel one stream per destructive reclamation, if
2233
+ there are more streams left, we can immediately post a new
2234
+ reclaimer in case the resource quota needs to free more
2235
+ memory */
2236
+ post_destructive_reclaimer(exec_ctx, t);
2237
+ }
2449
2238
  }
2450
- if (b == NULL) {
2451
- return 0;
2239
+ if (error != GRPC_ERROR_CANCELLED) {
2240
+ grpc_resource_user_finish_reclamation(
2241
+ exec_ctx, grpc_endpoint_get_resource_user(t->ep));
2452
2242
  }
2453
- return 0 == strcmp(a, b);
2243
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "destructive_reclaimer");
2244
+ }
2245
+
2246
+ /*******************************************************************************
2247
+ * TRACING
2248
+ */
2249
+
2250
+ static char *format_flowctl_context_var(const char *context, const char *var,
2251
+ int64_t val, uint32_t id) {
2252
+ char *name;
2253
+ if (context == NULL) {
2254
+ name = gpr_strdup(var);
2255
+ } else if (0 == strcmp(context, "t")) {
2256
+ GPR_ASSERT(id == 0);
2257
+ gpr_asprintf(&name, "TRANSPORT:%s", var);
2258
+ } else if (0 == strcmp(context, "s")) {
2259
+ GPR_ASSERT(id != 0);
2260
+ gpr_asprintf(&name, "STREAM[%d]:%s", id, var);
2261
+ } else {
2262
+ gpr_asprintf(&name, "BAD_CONTEXT[%s][%d]:%s", context, id, var);
2263
+ }
2264
+ char *name_fld = gpr_leftpad(name, ' ', 64);
2265
+ char *value;
2266
+ gpr_asprintf(&value, "%" PRId64, val);
2267
+ char *value_fld = gpr_leftpad(value, ' ', 8);
2268
+ char *result;
2269
+ gpr_asprintf(&result, "%s %s", name_fld, value_fld);
2270
+ gpr_free(name);
2271
+ gpr_free(name_fld);
2272
+ gpr_free(value);
2273
+ gpr_free(value_fld);
2274
+ return result;
2454
2275
  }
2455
2276
 
2456
2277
  void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
@@ -2458,26 +2279,18 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
2458
2279
  const char *var1, const char *context2,
2459
2280
  const char *var2, int is_client,
2460
2281
  uint32_t stream_id, int64_t val1, int64_t val2) {
2461
- char *scope1;
2462
- char *scope2;
2463
2282
  char *tmp_phase;
2464
- char *tmp_scope1;
2465
- char *label1 =
2466
- format_flowctl_context_var(context1, var1, val1, stream_id, &scope1);
2467
- char *label2 =
2468
- format_flowctl_context_var(context2, var2, val2, stream_id, &scope2);
2283
+ char *label1 = format_flowctl_context_var(context1, var1, val1, stream_id);
2284
+ char *label2 = format_flowctl_context_var(context2, var2, val2, stream_id);
2469
2285
  char *clisvr = is_client ? "client" : "server";
2470
2286
  char *prefix;
2471
2287
 
2472
2288
  tmp_phase = gpr_leftpad(phase, ' ', 8);
2473
- tmp_scope1 = gpr_leftpad(scope1, ' ', 11);
2474
- gpr_asprintf(&prefix, "FLOW %s: %s %s ", tmp_phase, clisvr, scope1);
2289
+ gpr_asprintf(&prefix, "FLOW %s: %s ", tmp_phase, clisvr);
2475
2290
  gpr_free(tmp_phase);
2476
- gpr_free(tmp_scope1);
2477
2291
 
2478
2292
  switch (op) {
2479
2293
  case GRPC_CHTTP2_FLOWCTL_MOVE:
2480
- GPR_ASSERT(samestr(scope1, scope2));
2481
2294
  if (val2 != 0) {
2482
2295
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
2483
2296
  "%sMOVE %s <- %s giving %" PRId64, prefix, label1, label2,
@@ -2502,8 +2315,6 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
2502
2315
  break;
2503
2316
  }
2504
2317
 
2505
- gpr_free(scope1);
2506
- gpr_free(scope2);
2507
2318
  gpr_free(label1);
2508
2319
  gpr_free(label2);
2509
2320
  gpr_free(prefix);
@@ -2517,6 +2328,14 @@ static char *chttp2_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
2517
2328
  return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
2518
2329
  }
2519
2330
 
2331
+ /*******************************************************************************
2332
+ * MONITORING
2333
+ */
2334
+ static grpc_endpoint *chttp2_get_endpoint(grpc_exec_ctx *exec_ctx,
2335
+ grpc_transport *t) {
2336
+ return ((grpc_chttp2_transport *)t)->ep;
2337
+ }
2338
+
2520
2339
  static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
2521
2340
  "chttp2",
2522
2341
  init_stream,
@@ -2526,7 +2345,8 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
2526
2345
  perform_transport_op,
2527
2346
  destroy_stream,
2528
2347
  destroy_transport,
2529
- chttp2_get_peer};
2348
+ chttp2_get_peer,
2349
+ chttp2_get_endpoint};
2530
2350
 
2531
2351
  grpc_transport *grpc_create_chttp2_transport(
2532
2352
  grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
@@ -2538,9 +2358,13 @@ grpc_transport *grpc_create_chttp2_transport(
2538
2358
 
2539
2359
  void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
2540
2360
  grpc_transport *transport,
2541
- gpr_slice *slices, size_t nslices) {
2361
+ grpc_slice_buffer *read_buffer) {
2542
2362
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
2543
- REF_TRANSPORT(t, "reading_action"); /* matches unref inside reading_action */
2544
- gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
2545
- reading_action(exec_ctx, t, GRPC_ERROR_NONE);
2363
+ GRPC_CHTTP2_REF_TRANSPORT(
2364
+ t, "reading_action"); /* matches unref inside reading_action */
2365
+ if (read_buffer != NULL) {
2366
+ grpc_slice_buffer_move_into(read_buffer, &t->read_buffer);
2367
+ gpr_free(read_buffer);
2368
+ }
2369
+ grpc_closure_sched(exec_ctx, &t->read_action_locked, GRPC_ERROR_NONE);
2546
2370
  }