grpc 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (459) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +29456 -0
  3. data/Rakefile +13 -8
  4. data/etc/roots.pem +5114 -0
  5. data/include/grpc/byte_buffer.h +120 -0
  6. data/include/grpc/byte_buffer_reader.h +58 -0
  7. data/include/grpc/census.h +488 -0
  8. data/include/grpc/compression.h +106 -0
  9. data/include/grpc/grpc.h +732 -0
  10. data/include/grpc/grpc_security.h +374 -0
  11. data/include/grpc/grpc_zookeeper.h +59 -0
  12. data/include/grpc/status.h +163 -0
  13. data/include/grpc/support/alloc.h +72 -0
  14. data/include/grpc/support/atm.h +92 -0
  15. data/include/grpc/support/atm_gcc_atomic.h +72 -0
  16. data/include/grpc/support/atm_gcc_sync.h +87 -0
  17. data/include/grpc/support/atm_win32.h +125 -0
  18. data/include/grpc/support/avl.h +91 -0
  19. data/include/grpc/support/cmdline.h +101 -0
  20. data/include/grpc/support/cpu.h +57 -0
  21. data/include/grpc/support/histogram.h +76 -0
  22. data/include/grpc/support/host_port.h +64 -0
  23. data/include/grpc/support/log.h +108 -0
  24. data/include/grpc/support/log_win32.h +51 -0
  25. data/include/grpc/support/port_platform.h +356 -0
  26. data/include/grpc/support/slice.h +182 -0
  27. data/include/grpc/support/slice_buffer.h +102 -0
  28. data/include/grpc/support/string_util.h +61 -0
  29. data/include/grpc/support/subprocess.h +57 -0
  30. data/include/grpc/support/sync.h +315 -0
  31. data/include/grpc/support/sync_generic.h +55 -0
  32. data/include/grpc/support/sync_posix.h +47 -0
  33. data/include/grpc/support/sync_win32.h +49 -0
  34. data/include/grpc/support/thd.h +91 -0
  35. data/include/grpc/support/time.h +128 -0
  36. data/include/grpc/support/tls.h +77 -0
  37. data/include/grpc/support/tls_gcc.h +56 -0
  38. data/include/grpc/support/tls_msvc.h +56 -0
  39. data/include/grpc/support/tls_pthread.h +60 -0
  40. data/include/grpc/support/useful.h +75 -0
  41. data/src/core/census/aggregation.h +66 -0
  42. data/src/core/census/context.c +46 -0
  43. data/src/core/census/context.h +47 -0
  44. data/src/core/census/grpc_context.c +53 -0
  45. data/src/core/census/grpc_filter.c +184 -0
  46. data/src/core/census/grpc_filter.h +44 -0
  47. data/src/core/census/initialize.c +57 -0
  48. data/src/core/census/operation.c +63 -0
  49. data/src/core/census/rpc_metric_id.h +51 -0
  50. data/src/core/census/tracing.c +45 -0
  51. data/src/core/channel/channel_args.c +209 -0
  52. data/src/core/channel/channel_args.h +88 -0
  53. data/src/core/channel/channel_stack.c +262 -0
  54. data/src/core/channel/channel_stack.h +260 -0
  55. data/src/core/channel/client_channel.c +524 -0
  56. data/src/core/channel/client_channel.h +63 -0
  57. data/src/core/channel/client_uchannel.c +243 -0
  58. data/src/core/channel/client_uchannel.h +60 -0
  59. data/src/core/channel/compress_filter.c +297 -0
  60. data/src/core/channel/compress_filter.h +65 -0
  61. data/src/core/channel/connected_channel.c +167 -0
  62. data/src/core/channel/connected_channel.h +51 -0
  63. data/src/core/channel/context.h +49 -0
  64. data/src/core/channel/http_client_filter.c +248 -0
  65. data/src/core/channel/http_client_filter.h +44 -0
  66. data/src/core/channel/http_server_filter.c +233 -0
  67. data/src/core/channel/http_server_filter.h +42 -0
  68. data/src/core/channel/subchannel_call_holder.c +259 -0
  69. data/src/core/channel/subchannel_call_holder.h +98 -0
  70. data/src/core/client_config/client_config.c +72 -0
  71. data/src/core/client_config/client_config.h +53 -0
  72. data/src/core/client_config/connector.c +54 -0
  73. data/src/core/client_config/connector.h +95 -0
  74. data/src/core/client_config/default_initial_connect_string.c +39 -0
  75. data/src/core/client_config/initial_connect_string.c +53 -0
  76. data/src/core/client_config/initial_connect_string.h +50 -0
  77. data/src/core/client_config/lb_policies/pick_first.c +398 -0
  78. data/src/core/client_config/lb_policies/pick_first.h +43 -0
  79. data/src/core/client_config/lb_policies/round_robin.c +537 -0
  80. data/src/core/client_config/lb_policies/round_robin.h +46 -0
  81. data/src/core/client_config/lb_policy.c +134 -0
  82. data/src/core/client_config/lb_policy.h +143 -0
  83. data/src/core/client_config/lb_policy_factory.c +48 -0
  84. data/src/core/client_config/lb_policy_factory.h +73 -0
  85. data/src/core/client_config/lb_policy_registry.c +88 -0
  86. data/src/core/client_config/lb_policy_registry.h +54 -0
  87. data/src/core/client_config/resolver.c +82 -0
  88. data/src/core/client_config/resolver.h +94 -0
  89. data/src/core/client_config/resolver_factory.c +55 -0
  90. data/src/core/client_config/resolver_factory.h +82 -0
  91. data/src/core/client_config/resolver_registry.c +137 -0
  92. data/src/core/client_config/resolver_registry.h +65 -0
  93. data/src/core/client_config/resolvers/dns_resolver.c +257 -0
  94. data/src/core/client_config/resolvers/dns_resolver.h +42 -0
  95. data/src/core/client_config/resolvers/sockaddr_resolver.c +391 -0
  96. data/src/core/client_config/resolvers/sockaddr_resolver.h +50 -0
  97. data/src/core/client_config/subchannel.c +697 -0
  98. data/src/core/client_config/subchannel.h +165 -0
  99. data/src/core/client_config/subchannel_factory.c +49 -0
  100. data/src/core/client_config/subchannel_factory.h +66 -0
  101. data/src/core/client_config/uri_parser.c +242 -0
  102. data/src/core/client_config/uri_parser.h +51 -0
  103. data/src/core/compression/algorithm.c +166 -0
  104. data/src/core/compression/algorithm_metadata.h +53 -0
  105. data/src/core/compression/message_compress.c +198 -0
  106. data/src/core/compression/message_compress.h +52 -0
  107. data/src/core/debug/trace.c +136 -0
  108. data/src/core/debug/trace.h +43 -0
  109. data/src/core/httpcli/format_request.c +120 -0
  110. data/src/core/httpcli/format_request.h +45 -0
  111. data/src/core/httpcli/httpcli.c +286 -0
  112. data/src/core/httpcli/httpcli.h +162 -0
  113. data/src/core/httpcli/httpcli_security_connector.c +189 -0
  114. data/src/core/httpcli/parser.c +211 -0
  115. data/src/core/httpcli/parser.h +64 -0
  116. data/src/core/iomgr/closure.c +98 -0
  117. data/src/core/iomgr/closure.h +97 -0
  118. data/src/core/iomgr/endpoint.c +67 -0
  119. data/src/core/iomgr/endpoint.h +102 -0
  120. data/src/core/iomgr/endpoint_pair.h +47 -0
  121. data/src/core/iomgr/endpoint_pair_posix.c +82 -0
  122. data/src/core/iomgr/endpoint_pair_windows.c +97 -0
  123. data/src/core/iomgr/exec_ctx.c +72 -0
  124. data/src/core/iomgr/exec_ctx.h +78 -0
  125. data/src/core/iomgr/executor.c +143 -0
  126. data/src/core/iomgr/executor.h +53 -0
  127. data/src/core/iomgr/fd_posix.c +438 -0
  128. data/src/core/iomgr/fd_posix.h +189 -0
  129. data/src/core/iomgr/iocp_windows.c +206 -0
  130. data/src/core/iomgr/iocp_windows.h +56 -0
  131. data/src/core/iomgr/iomgr.c +156 -0
  132. data/src/core/iomgr/iomgr.h +43 -0
  133. data/src/core/iomgr/iomgr_internal.h +58 -0
  134. data/src/core/iomgr/iomgr_posix.c +52 -0
  135. data/src/core/iomgr/iomgr_posix.h +39 -0
  136. data/src/core/iomgr/iomgr_windows.c +73 -0
  137. data/src/core/iomgr/pollset.h +95 -0
  138. data/src/core/iomgr/pollset_multipoller_with_epoll.c +258 -0
  139. data/src/core/iomgr/pollset_multipoller_with_poll_posix.c +227 -0
  140. data/src/core/iomgr/pollset_posix.c +638 -0
  141. data/src/core/iomgr/pollset_posix.h +147 -0
  142. data/src/core/iomgr/pollset_set.h +67 -0
  143. data/src/core/iomgr/pollset_set_posix.c +182 -0
  144. data/src/core/iomgr/pollset_set_posix.h +61 -0
  145. data/src/core/iomgr/pollset_set_windows.c +60 -0
  146. data/src/core/iomgr/pollset_set_windows.h +39 -0
  147. data/src/core/iomgr/pollset_windows.c +248 -0
  148. data/src/core/iomgr/pollset_windows.h +79 -0
  149. data/src/core/iomgr/resolve_address.h +72 -0
  150. data/src/core/iomgr/resolve_address_posix.c +183 -0
  151. data/src/core/iomgr/resolve_address_windows.c +166 -0
  152. data/src/core/iomgr/sockaddr.h +47 -0
  153. data/src/core/iomgr/sockaddr_posix.h +44 -0
  154. data/src/core/iomgr/sockaddr_utils.c +234 -0
  155. data/src/core/iomgr/sockaddr_utils.h +89 -0
  156. data/src/core/iomgr/sockaddr_win32.h +46 -0
  157. data/src/core/iomgr/socket_utils_common_posix.c +208 -0
  158. data/src/core/iomgr/socket_utils_linux.c +51 -0
  159. data/src/core/iomgr/socket_utils_posix.c +70 -0
  160. data/src/core/iomgr/socket_utils_posix.h +113 -0
  161. data/src/core/iomgr/socket_windows.c +98 -0
  162. data/src/core/iomgr/socket_windows.h +111 -0
  163. data/src/core/iomgr/tcp_client.h +53 -0
  164. data/src/core/iomgr/tcp_client_posix.c +304 -0
  165. data/src/core/iomgr/tcp_client_windows.c +221 -0
  166. data/src/core/iomgr/tcp_posix.c +485 -0
  167. data/src/core/iomgr/tcp_posix.h +65 -0
  168. data/src/core/iomgr/tcp_server.h +83 -0
  169. data/src/core/iomgr/tcp_server_posix.c +562 -0
  170. data/src/core/iomgr/tcp_server_windows.c +509 -0
  171. data/src/core/iomgr/tcp_windows.c +406 -0
  172. data/src/core/iomgr/tcp_windows.h +57 -0
  173. data/src/core/iomgr/time_averaged_stats.c +77 -0
  174. data/src/core/iomgr/time_averaged_stats.h +88 -0
  175. data/src/core/iomgr/timer.c +345 -0
  176. data/src/core/iomgr/timer.h +89 -0
  177. data/src/core/iomgr/timer_heap.c +148 -0
  178. data/src/core/iomgr/timer_heap.h +57 -0
  179. data/src/core/iomgr/timer_internal.h +61 -0
  180. data/src/core/iomgr/udp_server.c +439 -0
  181. data/src/core/iomgr/udp_server.h +83 -0
  182. data/src/core/iomgr/wakeup_fd_eventfd.c +85 -0
  183. data/src/core/iomgr/wakeup_fd_nospecial.c +51 -0
  184. data/src/core/iomgr/wakeup_fd_pipe.c +97 -0
  185. data/src/core/iomgr/wakeup_fd_pipe.h +41 -0
  186. data/src/core/iomgr/wakeup_fd_posix.c +72 -0
  187. data/src/core/iomgr/wakeup_fd_posix.h +101 -0
  188. data/src/core/iomgr/workqueue.h +85 -0
  189. data/src/core/iomgr/workqueue_posix.c +143 -0
  190. data/src/core/iomgr/workqueue_posix.h +51 -0
  191. data/src/core/iomgr/workqueue_windows.c +40 -0
  192. data/src/core/iomgr/workqueue_windows.h +37 -0
  193. data/src/core/json/json.c +64 -0
  194. data/src/core/json/json.h +88 -0
  195. data/src/core/json/json_common.h +49 -0
  196. data/src/core/json/json_reader.c +660 -0
  197. data/src/core/json/json_reader.h +160 -0
  198. data/src/core/json/json_string.c +379 -0
  199. data/src/core/json/json_writer.c +260 -0
  200. data/src/core/json/json_writer.h +97 -0
  201. data/src/core/profiling/basic_timers.c +274 -0
  202. data/src/core/profiling/stap_timers.c +65 -0
  203. data/src/core/profiling/timers.h +119 -0
  204. data/src/core/security/auth_filters.h +42 -0
  205. data/src/core/security/base64.c +233 -0
  206. data/src/core/security/base64.h +52 -0
  207. data/src/core/security/client_auth_filter.c +337 -0
  208. data/src/core/security/credentials.c +1273 -0
  209. data/src/core/security/credentials.h +376 -0
  210. data/src/core/security/credentials_metadata.c +101 -0
  211. data/src/core/security/credentials_posix.c +61 -0
  212. data/src/core/security/credentials_win32.c +61 -0
  213. data/src/core/security/google_default_credentials.c +260 -0
  214. data/src/core/security/handshake.c +327 -0
  215. data/src/core/security/handshake.h +50 -0
  216. data/src/core/security/json_token.c +405 -0
  217. data/src/core/security/json_token.h +118 -0
  218. data/src/core/security/jwt_verifier.c +842 -0
  219. data/src/core/security/jwt_verifier.h +136 -0
  220. data/src/core/security/secure_endpoint.c +383 -0
  221. data/src/core/security/secure_endpoint.h +49 -0
  222. data/src/core/security/security_connector.c +756 -0
  223. data/src/core/security/security_connector.h +246 -0
  224. data/src/core/security/security_context.c +342 -0
  225. data/src/core/security/security_context.h +114 -0
  226. data/src/core/security/server_auth_filter.c +264 -0
  227. data/src/core/security/server_secure_chttp2.c +268 -0
  228. data/src/core/statistics/census_interface.h +76 -0
  229. data/src/core/statistics/census_rpc_stats.h +101 -0
  230. data/src/core/support/alloc.c +90 -0
  231. data/src/core/support/avl.c +288 -0
  232. data/src/core/support/block_annotate.h +48 -0
  233. data/src/core/support/cmdline.c +347 -0
  234. data/src/core/support/cpu_iphone.c +49 -0
  235. data/src/core/support/cpu_linux.c +78 -0
  236. data/src/core/support/cpu_posix.c +77 -0
  237. data/src/core/support/cpu_windows.c +47 -0
  238. data/src/core/support/env.h +60 -0
  239. data/src/core/support/env_linux.c +62 -0
  240. data/src/core/support/env_posix.c +57 -0
  241. data/src/core/support/env_win32.c +65 -0
  242. data/src/core/support/file.c +91 -0
  243. data/src/core/support/file.h +63 -0
  244. data/src/core/support/file_posix.c +85 -0
  245. data/src/core/support/file_win32.c +84 -0
  246. data/src/core/support/histogram.c +244 -0
  247. data/src/core/support/host_port.c +110 -0
  248. data/src/core/support/log.c +66 -0
  249. data/src/core/support/log_android.c +87 -0
  250. data/src/core/support/log_linux.c +105 -0
  251. data/src/core/support/log_posix.c +102 -0
  252. data/src/core/support/log_win32.c +125 -0
  253. data/src/core/support/murmur_hash.c +96 -0
  254. data/src/core/support/murmur_hash.h +44 -0
  255. data/src/core/support/slice.c +343 -0
  256. data/src/core/support/slice_buffer.c +282 -0
  257. data/src/core/support/stack_lockfree.c +175 -0
  258. data/src/core/support/stack_lockfree.h +53 -0
  259. data/src/core/support/string.c +296 -0
  260. data/src/core/support/string.h +121 -0
  261. data/src/core/support/string_posix.c +86 -0
  262. data/src/core/support/string_win32.c +109 -0
  263. data/src/core/support/string_win32.h +47 -0
  264. data/src/core/support/subprocess_posix.c +112 -0
  265. data/src/core/support/sync.c +122 -0
  266. data/src/core/support/sync_posix.c +104 -0
  267. data/src/core/support/sync_win32.c +128 -0
  268. data/src/core/support/thd.c +64 -0
  269. data/src/core/support/thd_internal.h +39 -0
  270. data/src/core/support/thd_posix.c +94 -0
  271. data/src/core/support/thd_win32.c +117 -0
  272. data/src/core/support/time.c +304 -0
  273. data/src/core/support/time_posix.c +161 -0
  274. data/src/core/support/time_precise.c +89 -0
  275. data/src/core/support/time_precise.h +42 -0
  276. data/src/core/support/time_win32.c +101 -0
  277. data/src/core/support/tls_pthread.c +45 -0
  278. data/src/core/surface/api_trace.c +36 -0
  279. data/src/core/surface/api_trace.h +65 -0
  280. data/src/core/surface/byte_buffer.c +97 -0
  281. data/src/core/surface/byte_buffer_reader.c +123 -0
  282. data/src/core/surface/call.c +1424 -0
  283. data/src/core/surface/call.h +109 -0
  284. data/src/core/surface/call_details.c +50 -0
  285. data/src/core/surface/call_log_batch.c +118 -0
  286. data/src/core/surface/call_test_only.h +64 -0
  287. data/src/core/surface/channel.c +327 -0
  288. data/src/core/surface/channel.h +74 -0
  289. data/src/core/surface/channel_connectivity.c +220 -0
  290. data/src/core/surface/channel_create.c +235 -0
  291. data/src/core/surface/channel_ping.c +79 -0
  292. data/src/core/surface/completion_queue.c +481 -0
  293. data/src/core/surface/completion_queue.h +91 -0
  294. data/src/core/surface/event_string.c +81 -0
  295. data/src/core/surface/event_string.h +42 -0
  296. data/src/core/surface/init.c +168 -0
  297. data/src/core/surface/init.h +40 -0
  298. data/src/core/surface/init_secure.c +42 -0
  299. data/src/core/surface/lame_client.c +149 -0
  300. data/src/core/surface/metadata_array.c +49 -0
  301. data/src/core/surface/secure_channel_create.c +336 -0
  302. data/src/core/surface/server.c +1343 -0
  303. data/src/core/surface/server.h +67 -0
  304. data/src/core/surface/server_chttp2.c +149 -0
  305. data/src/core/surface/server_create.c +51 -0
  306. data/src/core/surface/surface_trace.h +48 -0
  307. data/src/core/surface/validate_metadata.c +73 -0
  308. data/src/core/surface/version.c +39 -0
  309. data/src/core/transport/byte_stream.c +76 -0
  310. data/src/core/transport/byte_stream.h +88 -0
  311. data/src/core/transport/chttp2/alpn.c +56 -0
  312. data/src/core/transport/chttp2/alpn.h +49 -0
  313. data/src/core/transport/chttp2/bin_encoder.c +285 -0
  314. data/src/core/transport/chttp2/bin_encoder.h +54 -0
  315. data/src/core/transport/chttp2/frame.h +69 -0
  316. data/src/core/transport/chttp2/frame_data.c +245 -0
  317. data/src/core/transport/chttp2/frame_data.h +101 -0
  318. data/src/core/transport/chttp2/frame_goaway.c +193 -0
  319. data/src/core/transport/chttp2/frame_goaway.h +77 -0
  320. data/src/core/transport/chttp2/frame_ping.c +97 -0
  321. data/src/core/transport/chttp2/frame_ping.h +56 -0
  322. data/src/core/transport/chttp2/frame_rst_stream.c +100 -0
  323. data/src/core/transport/chttp2/frame_rst_stream.h +55 -0
  324. data/src/core/transport/chttp2/frame_settings.c +259 -0
  325. data/src/core/transport/chttp2/frame_settings.h +103 -0
  326. data/src/core/transport/chttp2/frame_window_update.c +114 -0
  327. data/src/core/transport/chttp2/frame_window_update.h +58 -0
  328. data/src/core/transport/chttp2/hpack_encoder.c +572 -0
  329. data/src/core/transport/chttp2/hpack_encoder.h +95 -0
  330. data/src/core/transport/chttp2/hpack_parser.c +1449 -0
  331. data/src/core/transport/chttp2/hpack_parser.h +116 -0
  332. data/src/core/transport/chttp2/hpack_table.c +361 -0
  333. data/src/core/transport/chttp2/hpack_table.h +108 -0
  334. data/src/core/transport/chttp2/http2_errors.h +56 -0
  335. data/src/core/transport/chttp2/huffsyms.c +297 -0
  336. data/src/core/transport/chttp2/huffsyms.h +48 -0
  337. data/src/core/transport/chttp2/incoming_metadata.c +96 -0
  338. data/src/core/transport/chttp2/incoming_metadata.h +60 -0
  339. data/src/core/transport/chttp2/internal.h +757 -0
  340. data/src/core/transport/chttp2/parsing.c +866 -0
  341. data/src/core/transport/chttp2/status_conversion.c +109 -0
  342. data/src/core/transport/chttp2/status_conversion.h +50 -0
  343. data/src/core/transport/chttp2/stream_lists.c +401 -0
  344. data/src/core/transport/chttp2/stream_map.c +198 -0
  345. data/src/core/transport/chttp2/stream_map.h +85 -0
  346. data/src/core/transport/chttp2/timeout_encoding.c +185 -0
  347. data/src/core/transport/chttp2/timeout_encoding.h +47 -0
  348. data/src/core/transport/chttp2/varint.c +66 -0
  349. data/src/core/transport/chttp2/varint.h +76 -0
  350. data/src/core/transport/chttp2/writing.c +356 -0
  351. data/src/core/transport/chttp2_transport.c +1692 -0
  352. data/src/core/transport/chttp2_transport.h +51 -0
  353. data/src/core/transport/connectivity_state.c +164 -0
  354. data/src/core/transport/connectivity_state.h +85 -0
  355. data/src/core/transport/metadata.c +690 -0
  356. data/src/core/transport/metadata.h +156 -0
  357. data/src/core/transport/metadata_batch.c +194 -0
  358. data/src/core/transport/metadata_batch.h +125 -0
  359. data/src/core/transport/static_metadata.c +90 -0
  360. data/src/core/transport/static_metadata.h +408 -0
  361. data/src/core/transport/transport.c +183 -0
  362. data/src/core/transport/transport.h +222 -0
  363. data/src/core/transport/transport_impl.h +78 -0
  364. data/src/core/transport/transport_op_string.c +140 -0
  365. data/src/core/tsi/fake_transport_security.c +525 -0
  366. data/src/core/tsi/fake_transport_security.h +61 -0
  367. data/src/core/tsi/ssl_transport_security.c +1467 -0
  368. data/src/core/tsi/ssl_transport_security.h +173 -0
  369. data/src/core/tsi/transport_security.c +284 -0
  370. data/src/core/tsi/transport_security.h +111 -0
  371. data/src/core/tsi/transport_security_interface.h +344 -0
  372. data/{bin → src/ruby/bin}/apis/google/protobuf/empty.rb +0 -0
  373. data/{bin → src/ruby/bin}/apis/pubsub_demo.rb +7 -15
  374. data/{bin → src/ruby/bin}/apis/tech/pubsub/proto/pubsub.rb +0 -0
  375. data/{bin → src/ruby/bin}/apis/tech/pubsub/proto/pubsub_services.rb +0 -0
  376. data/{bin → src/ruby/bin}/grpc_ruby_interop_client +0 -0
  377. data/{bin → src/ruby/bin}/grpc_ruby_interop_server +0 -0
  378. data/{bin → src/ruby/bin}/interop/interop_client.rb +0 -0
  379. data/{bin → src/ruby/bin}/interop/interop_server.rb +0 -0
  380. data/src/ruby/bin/math.rb +32 -0
  381. data/{bin → src/ruby/bin}/math_client.rb +1 -1
  382. data/{bin → src/ruby/bin}/math_server.rb +1 -1
  383. data/src/ruby/bin/math_services.rb +27 -0
  384. data/{bin → src/ruby/bin}/noproto_client.rb +1 -1
  385. data/{bin → src/ruby/bin}/noproto_server.rb +1 -1
  386. data/{ext → src/ruby/ext}/grpc/extconf.rb +24 -40
  387. data/{ext → src/ruby/ext}/grpc/rb_byte_buffer.c +0 -0
  388. data/{ext → src/ruby/ext}/grpc/rb_byte_buffer.h +0 -0
  389. data/{ext → src/ruby/ext}/grpc/rb_call.c +80 -18
  390. data/{ext → src/ruby/ext}/grpc/rb_call.h +6 -0
  391. data/src/ruby/ext/grpc/rb_call_credentials.c +315 -0
  392. data/src/ruby/ext/grpc/rb_call_credentials.h +46 -0
  393. data/{ext → src/ruby/ext}/grpc/rb_channel.c +19 -7
  394. data/{ext → src/ruby/ext}/grpc/rb_channel.h +0 -0
  395. data/{ext → src/ruby/ext}/grpc/rb_channel_args.c +2 -0
  396. data/{ext → src/ruby/ext}/grpc/rb_channel_args.h +0 -0
  397. data/src/ruby/ext/grpc/rb_channel_credentials.c +266 -0
  398. data/{ext/grpc/rb_credentials.h → src/ruby/ext/grpc/rb_channel_credentials.h} +3 -3
  399. data/{ext → src/ruby/ext}/grpc/rb_completion_queue.c +3 -1
  400. data/{ext → src/ruby/ext}/grpc/rb_completion_queue.h +0 -0
  401. data/src/ruby/ext/grpc/rb_event_thread.c +153 -0
  402. data/src/ruby/ext/grpc/rb_event_thread.h +37 -0
  403. data/{ext → src/ruby/ext}/grpc/rb_grpc.c +25 -5
  404. data/{ext → src/ruby/ext}/grpc/rb_grpc.h +0 -0
  405. data/{ext → src/ruby/ext}/grpc/rb_server.c +4 -1
  406. data/{ext → src/ruby/ext}/grpc/rb_server.h +0 -0
  407. data/{ext → src/ruby/ext}/grpc/rb_server_credentials.c +2 -0
  408. data/{ext → src/ruby/ext}/grpc/rb_server_credentials.h +0 -0
  409. data/{lib → src/ruby/lib}/grpc.rb +6 -1
  410. data/{lib → src/ruby/lib}/grpc/core/time_consts.rb +0 -0
  411. data/{lib → src/ruby/lib}/grpc/errors.rb +0 -0
  412. data/{lib → src/ruby/lib}/grpc/generic/active_call.rb +4 -6
  413. data/{lib → src/ruby/lib}/grpc/generic/bidi_call.rb +16 -4
  414. data/{lib → src/ruby/lib}/grpc/generic/client_stub.rb +42 -52
  415. data/{lib → src/ruby/lib}/grpc/generic/rpc_desc.rb +0 -0
  416. data/{lib → src/ruby/lib}/grpc/generic/rpc_server.rb +15 -8
  417. data/{lib → src/ruby/lib}/grpc/generic/service.rb +4 -2
  418. data/src/ruby/lib/grpc/grpc.so +0 -0
  419. data/{lib → src/ruby/lib}/grpc/logconfig.rb +0 -0
  420. data/{lib → src/ruby/lib}/grpc/notifier.rb +0 -0
  421. data/{lib → src/ruby/lib}/grpc/version.rb +2 -2
  422. data/src/ruby/pb/README.md +42 -0
  423. data/src/ruby/pb/generate_proto_ruby.sh +51 -0
  424. data/src/ruby/pb/grpc/health/checker.rb +75 -0
  425. data/src/ruby/pb/grpc/health/v1alpha/health.rb +29 -0
  426. data/src/ruby/pb/grpc/health/v1alpha/health_services.rb +28 -0
  427. data/src/ruby/pb/test/client.rb +469 -0
  428. data/src/ruby/pb/test/proto/empty.rb +15 -0
  429. data/src/ruby/pb/test/proto/messages.rb +80 -0
  430. data/src/ruby/pb/test/proto/test.rb +14 -0
  431. data/src/ruby/pb/test/proto/test_services.rb +64 -0
  432. data/src/ruby/pb/test/server.rb +253 -0
  433. data/{bin/math_services.rb → src/ruby/spec/call_credentials_spec.rb} +19 -18
  434. data/{spec → src/ruby/spec}/call_spec.rb +10 -1
  435. data/{spec/credentials_spec.rb → src/ruby/spec/channel_credentials_spec.rb} +38 -12
  436. data/{spec → src/ruby/spec}/channel_spec.rb +14 -9
  437. data/{spec → src/ruby/spec}/client_server_spec.rb +31 -2
  438. data/{spec → src/ruby/spec}/completion_queue_spec.rb +0 -0
  439. data/{spec → src/ruby/spec}/generic/active_call_spec.rb +2 -1
  440. data/{spec → src/ruby/spec}/generic/client_stub_spec.rb +27 -67
  441. data/{spec → src/ruby/spec}/generic/rpc_desc_spec.rb +0 -0
  442. data/{spec → src/ruby/spec}/generic/rpc_server_pool_spec.rb +0 -0
  443. data/{spec → src/ruby/spec}/generic/rpc_server_spec.rb +12 -46
  444. data/{spec → src/ruby/spec}/generic/service_spec.rb +6 -3
  445. data/{spec → src/ruby/spec}/pb/health/checker_spec.rb +8 -8
  446. data/{spec → src/ruby/spec}/server_credentials_spec.rb +0 -0
  447. data/{spec → src/ruby/spec}/server_spec.rb +0 -0
  448. data/{spec → src/ruby/spec}/spec_helper.rb +0 -0
  449. data/{spec → src/ruby/spec}/testdata/README +0 -0
  450. data/{spec → src/ruby/spec}/testdata/ca.pem +0 -0
  451. data/{spec → src/ruby/spec}/testdata/server1.key +0 -0
  452. data/src/ruby/spec/testdata/server1.pem +16 -0
  453. data/{spec → src/ruby/spec}/time_consts_spec.rb +0 -0
  454. metadata +496 -97
  455. data/bin/math.proto +0 -80
  456. data/bin/math.rb +0 -61
  457. data/ext/grpc/rb_credentials.c +0 -294
  458. data/lib/grpc/grpc.so +0 -0
  459. data/spec/testdata/server1.pem +0 -16
@@ -0,0 +1,1692 @@
1
+ /*
2
+ *
3
+ * Copyright 2015, Google Inc.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are
8
+ * met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above
13
+ * copyright notice, this list of conditions and the following disclaimer
14
+ * in the documentation and/or other materials provided with the
15
+ * distribution.
16
+ * * Neither the name of Google Inc. nor the names of its
17
+ * contributors may be used to endorse or promote products derived from
18
+ * this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ *
32
+ */
33
+
34
+ #include "src/core/transport/chttp2_transport.h"
35
+
36
+ #include <math.h>
37
+ #include <stdio.h>
38
+ #include <string.h>
39
+
40
+ #include <grpc/support/alloc.h>
41
+ #include <grpc/support/log.h>
42
+ #include <grpc/support/slice_buffer.h>
43
+ #include <grpc/support/string_util.h>
44
+ #include <grpc/support/useful.h>
45
+
46
+ #include "src/core/profiling/timers.h"
47
+ #include "src/core/support/string.h"
48
+ #include "src/core/transport/chttp2/http2_errors.h"
49
+ #include "src/core/transport/chttp2/internal.h"
50
+ #include "src/core/transport/chttp2/status_conversion.h"
51
+ #include "src/core/transport/chttp2/timeout_encoding.h"
52
+ #include "src/core/transport/static_metadata.h"
53
+ #include "src/core/transport/transport_impl.h"
54
+
55
+ #define DEFAULT_WINDOW 65535
56
+ #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
57
+ #define MAX_WINDOW 0x7fffffffu
58
+
59
+ #define MAX_CLIENT_STREAM_ID 0x7fffffffu
60
+
61
+ int grpc_http_trace = 0;
62
+ int grpc_flowctl_trace = 0;
63
+
64
+ #define TRANSPORT_FROM_WRITING(tw) \
65
+ ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
66
+ writing)))
67
+
68
+ #define TRANSPORT_FROM_PARSING(tw) \
69
+ ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
70
+ parsing)))
71
+
72
+ #define TRANSPORT_FROM_GLOBAL(tg) \
73
+ ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
74
+ global)))
75
+
76
+ #define STREAM_FROM_GLOBAL(sg) \
77
+ ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
78
+
79
+ #define STREAM_FROM_PARSING(sg) \
80
+ ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, parsing)))
81
+
82
+ static const grpc_transport_vtable vtable;
83
+
84
+ static void lock(grpc_chttp2_transport *t);
85
+ static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
86
+
87
+ /* forward declarations of various callbacks that we'll build closures around */
88
+ static void writing_action(grpc_exec_ctx *exec_ctx, void *t,
89
+ int iomgr_success_ignored);
90
+
91
+ /** Set a transport level setting, and push it to our peer */
92
+ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
93
+ gpr_uint32 value);
94
+
95
+ /** Endpoint callback to process incoming data */
96
+ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, int success);
97
+
98
+ /** Start disconnection chain */
99
+ static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
100
+
101
+ /** Perform a transport_op */
102
+ static void perform_stream_op_locked(
103
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
104
+ grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op);
105
+
106
+ /** Cancel a stream: coming from the transport API */
107
+ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
108
+ grpc_chttp2_transport_global *transport_global,
109
+ grpc_chttp2_stream_global *stream_global,
110
+ grpc_status_code status);
111
+
112
+ static void close_from_api(grpc_exec_ctx *exec_ctx,
113
+ grpc_chttp2_transport_global *transport_global,
114
+ grpc_chttp2_stream_global *stream_global,
115
+ grpc_status_code status,
116
+ gpr_slice *optional_message);
117
+
118
+ /** Add endpoint from this transport to pollset */
119
+ static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
120
+ grpc_chttp2_transport *t,
121
+ grpc_pollset *pollset);
122
+ static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
123
+ grpc_chttp2_transport *t,
124
+ grpc_pollset_set *pollset_set);
125
+
126
+ /** Start new streams that have been created if we can */
127
+ static void maybe_start_some_streams(
128
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global);
129
+
130
+ static void connectivity_state_set(
131
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
132
+ grpc_connectivity_state state, const char *reason);
133
+
134
+ static void check_read_ops(grpc_exec_ctx *exec_ctx,
135
+ grpc_chttp2_transport_global *transport_global);
136
+
137
+ static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
138
+ grpc_chttp2_stream_global *stream_global);
139
+
140
+ /*
141
+ * CONSTRUCTION/DESTRUCTION/REFCOUNTING
142
+ */
143
+
144
+ static void destruct_transport(grpc_exec_ctx *exec_ctx,
145
+ grpc_chttp2_transport *t) {
146
+ size_t i;
147
+
148
+ gpr_mu_lock(&t->mu);
149
+
150
+ GPR_ASSERT(t->ep == NULL);
151
+
152
+ gpr_slice_buffer_destroy(&t->global.qbuf);
153
+
154
+ gpr_slice_buffer_destroy(&t->writing.outbuf);
155
+ grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor);
156
+
157
+ gpr_slice_buffer_destroy(&t->parsing.qbuf);
158
+ gpr_slice_buffer_destroy(&t->read_buffer);
159
+ grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser);
160
+ grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser);
161
+
162
+ for (i = 0; i < STREAM_LIST_COUNT; i++) {
163
+ GPR_ASSERT(t->lists[i].head == NULL);
164
+ GPR_ASSERT(t->lists[i].tail == NULL);
165
+ }
166
+
167
+ GPR_ASSERT(grpc_chttp2_stream_map_size(&t->parsing_stream_map) == 0);
168
+ GPR_ASSERT(grpc_chttp2_stream_map_size(&t->new_stream_map) == 0);
169
+
170
+ grpc_chttp2_stream_map_destroy(&t->parsing_stream_map);
171
+ grpc_chttp2_stream_map_destroy(&t->new_stream_map);
172
+ grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
173
+
174
+ gpr_mu_unlock(&t->mu);
175
+ gpr_mu_destroy(&t->mu);
176
+
177
+ /* callback remaining pings: they're not allowed to call into the transpot,
178
+ and maybe they hold resources that need to be freed */
179
+ while (t->global.pings.next != &t->global.pings) {
180
+ grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
181
+ grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, 0);
182
+ ping->next->prev = ping->prev;
183
+ ping->prev->next = ping->next;
184
+ gpr_free(ping);
185
+ }
186
+
187
+ gpr_free(t->peer_string);
188
+ gpr_free(t);
189
+ }
190
+
191
+ #ifdef REFCOUNTING_DEBUG
192
+ #define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__)
193
+ #define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t, r, __FILE__, __LINE__)
194
+ static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
195
+ const char *reason, const char *file, int line) {
196
+ gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count,
197
+ t->refs.count - 1, reason, file, line);
198
+ if (!gpr_unref(&t->refs)) return;
199
+ destruct_transport(exec_ctx, t);
200
+ }
201
+
202
+ static void ref_transport(grpc_chttp2_transport *t, const char *reason,
203
+ const char *file, int line) {
204
+ gpr_log(GPR_DEBUG, "chttp2: ref:%p %d->%d %s [%s:%d]", t, t->refs.count,
205
+ t->refs.count + 1, reason, file, line);
206
+ gpr_ref(&t->refs);
207
+ }
208
+ #else
209
+ #define REF_TRANSPORT(t, r) ref_transport(t)
210
+ #define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t)
211
+ static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
212
+ if (!gpr_unref(&t->refs)) return;
213
+ destruct_transport(exec_ctx, t);
214
+ }
215
+
216
+ static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
217
+ #endif
218
+
219
+ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
220
+ const grpc_channel_args *channel_args,
221
+ grpc_endpoint *ep, gpr_uint8 is_client) {
222
+ size_t i;
223
+ int j;
224
+
225
+ GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
226
+ GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
227
+
228
+ memset(t, 0, sizeof(*t));
229
+
230
+ t->base.vtable = &vtable;
231
+ t->ep = ep;
232
+ /* one ref is for destroy, the other for when ep becomes NULL */
233
+ gpr_ref_init(&t->refs, 2);
234
+ /* ref is dropped at transport close() */
235
+ gpr_ref_init(&t->shutdown_ep_refs, 1);
236
+ gpr_mu_init(&t->mu);
237
+ t->peer_string = grpc_endpoint_get_peer(ep);
238
+ t->endpoint_reading = 1;
239
+ t->global.next_stream_id = is_client ? 1 : 2;
240
+ t->global.is_client = is_client;
241
+ t->writing.outgoing_window = DEFAULT_WINDOW;
242
+ t->parsing.incoming_window = DEFAULT_WINDOW;
243
+ t->global.stream_lookahead = DEFAULT_WINDOW;
244
+ t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
245
+ t->global.ping_counter = 1;
246
+ t->global.pings.next = t->global.pings.prev = &t->global.pings;
247
+ t->parsing.is_client = is_client;
248
+ t->parsing.deframe_state =
249
+ is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
250
+ t->writing.is_client = is_client;
251
+ grpc_connectivity_state_init(
252
+ &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
253
+ is_client ? "client_transport" : "server_transport");
254
+
255
+ gpr_slice_buffer_init(&t->global.qbuf);
256
+
257
+ gpr_slice_buffer_init(&t->writing.outbuf);
258
+ grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor);
259
+ grpc_closure_init(&t->writing_action, writing_action, t);
260
+
261
+ gpr_slice_buffer_init(&t->parsing.qbuf);
262
+ grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser);
263
+ grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser);
264
+
265
+ grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing,
266
+ &t->writing);
267
+ grpc_closure_init(&t->recv_data, recv_data, t);
268
+ gpr_slice_buffer_init(&t->read_buffer);
269
+
270
+ if (is_client) {
271
+ gpr_slice_buffer_add(
272
+ &t->global.qbuf,
273
+ gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
274
+ }
275
+ /* 8 is a random stab in the dark as to a good initial size: it's small enough
276
+ that it shouldn't waste memory for infrequently used connections, yet
277
+ large enough that the exponential growth should happen nicely when it's
278
+ needed.
279
+ TODO(ctiller): tune this */
280
+ grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8);
281
+ grpc_chttp2_stream_map_init(&t->new_stream_map, 8);
282
+
283
+ /* copy in initial settings to all setting sets */
284
+ for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) {
285
+ t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value;
286
+ for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) {
287
+ t->global.settings[j][i] =
288
+ grpc_chttp2_settings_parameters[i].default_value;
289
+ }
290
+ }
291
+ t->global.dirtied_local_settings = 1;
292
+ /* Hack: it's common for implementations to assume 65536 bytes initial send
293
+ window -- this should by rights be 0 */
294
+ t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
295
+ t->global.sent_local_settings = 0;
296
+
297
+ /* configure http2 the way we like it */
298
+ if (is_client) {
299
+ push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
300
+ push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
301
+ }
302
+ push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW);
303
+
304
+ if (channel_args) {
305
+ for (i = 0; i < channel_args->num_args; i++) {
306
+ if (0 ==
307
+ strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) {
308
+ if (is_client) {
309
+ gpr_log(GPR_ERROR, "%s: is ignored on the client",
310
+ GRPC_ARG_MAX_CONCURRENT_STREAMS);
311
+ } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
312
+ gpr_log(GPR_ERROR, "%s: must be an integer",
313
+ GRPC_ARG_MAX_CONCURRENT_STREAMS);
314
+ } else {
315
+ push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
316
+ (gpr_uint32)channel_args->args[i].value.integer);
317
+ }
318
+ } else if (0 == strcmp(channel_args->args[i].key,
319
+ GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
320
+ if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
321
+ gpr_log(GPR_ERROR, "%s: must be an integer",
322
+ GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER);
323
+ } else if ((t->global.next_stream_id & 1) !=
324
+ (channel_args->args[i].value.integer & 1)) {
325
+ gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
326
+ GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER,
327
+ t->global.next_stream_id & 1,
328
+ is_client ? "client" : "server");
329
+ } else {
330
+ t->global.next_stream_id =
331
+ (gpr_uint32)channel_args->args[i].value.integer;
332
+ }
333
+ } else if (0 == strcmp(channel_args->args[i].key,
334
+ GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
335
+ if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
336
+ gpr_log(GPR_ERROR, "%s: must be an integer",
337
+ GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
338
+ } else if (channel_args->args[i].value.integer <= 5) {
339
+ gpr_log(GPR_ERROR, "%s: must be at least 5",
340
+ GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
341
+ } else {
342
+ t->global.stream_lookahead =
343
+ (gpr_uint32)channel_args->args[i].value.integer;
344
+ }
345
+ } else if (0 == strcmp(channel_args->args[i].key,
346
+ GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) {
347
+ if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
348
+ gpr_log(GPR_ERROR, "%s: must be an integer",
349
+ GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
350
+ } else if (channel_args->args[i].value.integer < 0) {
351
+ gpr_log(GPR_DEBUG, "%s: must be non-negative",
352
+ GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
353
+ } else {
354
+ push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
355
+ (gpr_uint32)channel_args->args[i].value.integer);
356
+ }
357
+ } else if (0 == strcmp(channel_args->args[i].key,
358
+ GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
359
+ if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
360
+ gpr_log(GPR_ERROR, "%s: must be an integer",
361
+ GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
362
+ } else if (channel_args->args[i].value.integer < 0) {
363
+ gpr_log(GPR_DEBUG, "%s: must be non-negative",
364
+ GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
365
+ } else {
366
+ grpc_chttp2_hpack_compressor_set_max_usable_size(
367
+ &t->writing.hpack_compressor,
368
+ (gpr_uint32)channel_args->args[i].value.integer);
369
+ }
370
+ }
371
+ }
372
+ }
373
+ }
374
+
375
+ static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
376
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
377
+
378
+ lock(t);
379
+ t->destroying = 1;
380
+ drop_connection(exec_ctx, t);
381
+ unlock(exec_ctx, t);
382
+
383
+ UNREF_TRANSPORT(exec_ctx, t, "destroy");
384
+ }
385
+
386
+ /** block grpc_endpoint_shutdown being called until a paired
387
+ allow_endpoint_shutdown is made */
388
+ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) {
389
+ GPR_ASSERT(t->ep);
390
+ gpr_ref(&t->shutdown_ep_refs);
391
+ }
392
+
393
+ static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx,
394
+ grpc_chttp2_transport *t) {
395
+ if (gpr_unref(&t->shutdown_ep_refs)) {
396
+ if (t->ep) {
397
+ grpc_endpoint_shutdown(exec_ctx, t->ep);
398
+ }
399
+ }
400
+ }
401
+
402
+ static void allow_endpoint_shutdown_unlocked(grpc_exec_ctx *exec_ctx,
403
+ grpc_chttp2_transport *t) {
404
+ if (gpr_unref(&t->shutdown_ep_refs)) {
405
+ gpr_mu_lock(&t->mu);
406
+ if (t->ep) {
407
+ grpc_endpoint_shutdown(exec_ctx, t->ep);
408
+ }
409
+ gpr_mu_unlock(&t->mu);
410
+ }
411
+ }
412
+
413
+ static void destroy_endpoint(grpc_exec_ctx *exec_ctx,
414
+ grpc_chttp2_transport *t) {
415
+ grpc_endpoint_destroy(exec_ctx, t->ep);
416
+ t->ep = NULL;
417
+ /* safe because we'll still have the ref for write */
418
+ UNREF_TRANSPORT(exec_ctx, t, "disconnect");
419
+ }
420
+
421
+ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
422
+ grpc_chttp2_transport *t) {
423
+ if (!t->closed) {
424
+ t->closed = 1;
425
+ connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_FATAL_FAILURE,
426
+ "close_transport");
427
+ if (t->ep) {
428
+ allow_endpoint_shutdown_locked(exec_ctx, t);
429
+ }
430
+ }
431
+ }
432
+
433
+ #ifdef GRPC_STREAM_REFCOUNT_DEBUG
434
+ void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global,
435
+ const char *reason) {
436
+ grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount, reason);
437
+ }
438
+ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
439
+ grpc_chttp2_stream_global *stream_global,
440
+ const char *reason) {
441
+ grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount,
442
+ reason);
443
+ }
444
+ #else
445
+ void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global) {
446
+ grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount);
447
+ }
448
+ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
449
+ grpc_chttp2_stream_global *stream_global) {
450
+ grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount);
451
+ }
452
+ #endif
453
+
454
+ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
455
+ grpc_stream *gs, grpc_stream_refcount *refcount,
456
+ const void *server_data) {
457
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
458
+ grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
459
+
460
+ memset(s, 0, sizeof(*s));
461
+
462
+ s->refcount = refcount;
463
+ GRPC_CHTTP2_STREAM_REF(&s->global, "chttp2");
464
+
465
+ grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[0]);
466
+ grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[1]);
467
+ grpc_chttp2_incoming_metadata_buffer_init(
468
+ &s->global.received_initial_metadata);
469
+ grpc_chttp2_incoming_metadata_buffer_init(
470
+ &s->global.received_trailing_metadata);
471
+ grpc_chttp2_data_parser_init(&s->parsing.data_parser);
472
+ gpr_slice_buffer_init(&s->writing.flow_controlled_buffer);
473
+
474
+ REF_TRANSPORT(t, "stream");
475
+
476
+ lock(t);
477
+ grpc_chttp2_register_stream(t, s);
478
+ if (server_data) {
479
+ GPR_ASSERT(t->parsing_active);
480
+ s->global.id = (gpr_uint32)(gpr_uintptr)server_data;
481
+ s->parsing.id = s->global.id;
482
+ s->global.outgoing_window =
483
+ t->global.settings[GRPC_PEER_SETTINGS]
484
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
485
+ s->parsing.incoming_window = s->global.max_recv_bytes =
486
+ t->global.settings[GRPC_SENT_SETTINGS]
487
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
488
+ *t->accepting_stream = s;
489
+ grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s);
490
+ s->global.in_stream_map = 1;
491
+ }
492
+ unlock(exec_ctx, t);
493
+
494
+ return 0;
495
+ }
496
+
497
+ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
498
+ grpc_stream *gs) {
499
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
500
+ grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
501
+ int i;
502
+ grpc_byte_stream *bs;
503
+
504
+ GPR_TIMER_BEGIN("destroy_stream", 0);
505
+
506
+ gpr_mu_lock(&t->mu);
507
+
508
+ GPR_ASSERT((s->global.write_closed && s->global.read_closed) ||
509
+ s->global.id == 0);
510
+ GPR_ASSERT(!s->global.in_stream_map);
511
+ if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
512
+ close_transport_locked(exec_ctx, t);
513
+ }
514
+ if (!t->parsing_active && s->global.id) {
515
+ GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
516
+ s->global.id) == NULL);
517
+ }
518
+
519
+ grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
520
+ grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global,
521
+ &s->global);
522
+
523
+ gpr_mu_unlock(&t->mu);
524
+
525
+ for (i = 0; i < STREAM_LIST_COUNT; i++) {
526
+ if (s->included[i]) {
527
+ gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
528
+ t->global.is_client ? "client" : "server", s->global.id, i);
529
+ abort();
530
+ }
531
+ }
532
+
533
+ while (
534
+ (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) {
535
+ grpc_byte_stream_destroy(bs);
536
+ }
537
+
538
+ GPR_ASSERT(s->global.send_initial_metadata_finished == NULL);
539
+ GPR_ASSERT(s->global.send_message_finished == NULL);
540
+ GPR_ASSERT(s->global.send_trailing_metadata_finished == NULL);
541
+ GPR_ASSERT(s->global.recv_initial_metadata_finished == NULL);
542
+ GPR_ASSERT(s->global.recv_message_ready == NULL);
543
+ GPR_ASSERT(s->global.recv_trailing_metadata_finished == NULL);
544
+ grpc_chttp2_data_parser_destroy(exec_ctx, &s->parsing.data_parser);
545
+ grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[0]);
546
+ grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[1]);
547
+ grpc_chttp2_incoming_metadata_buffer_destroy(
548
+ &s->global.received_initial_metadata);
549
+ grpc_chttp2_incoming_metadata_buffer_destroy(
550
+ &s->global.received_trailing_metadata);
551
+ gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer);
552
+
553
+ UNREF_TRANSPORT(exec_ctx, t, "stream");
554
+
555
+ GPR_TIMER_END("destroy_stream", 0);
556
+ }
557
+
558
+ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
559
+ grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id) {
560
+ grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
561
+ grpc_chttp2_stream *s =
562
+ grpc_chttp2_stream_map_find(&t->parsing_stream_map, id);
563
+ return s ? &s->parsing : NULL;
564
+ }
565
+
566
+ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
567
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
568
+ gpr_uint32 id) {
569
+ grpc_chttp2_stream *accepting;
570
+ grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
571
+ GPR_ASSERT(t->accepting_stream == NULL);
572
+ t->accepting_stream = &accepting;
573
+ t->channel_callback.accept_stream(exec_ctx,
574
+ t->channel_callback.accept_stream_user_data,
575
+ &t->base, (void *)(gpr_uintptr)id);
576
+ t->accepting_stream = NULL;
577
+ return &accepting->parsing;
578
+ }
579
+
580
+ /*
581
+ * LOCK MANAGEMENT
582
+ */
583
+
584
+ /* We take a grpc_chttp2_transport-global lock in response to calls coming in
585
+ from above,
586
+ and in response to data being received from below. New data to be written
587
+ is always queued, as are callbacks to process data. During unlock() we
588
+ check our todo lists and initiate callbacks and flush writes. */
589
+
590
+ static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
591
+
592
+ static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
593
+ GPR_TIMER_BEGIN("unlock", 0);
594
+ if (!t->writing_active && !t->closed &&
595
+ grpc_chttp2_unlocking_check_writes(&t->global, &t->writing,
596
+ t->parsing_active)) {
597
+ t->writing_active = 1;
598
+ REF_TRANSPORT(t, "writing");
599
+ grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, 1);
600
+ prevent_endpoint_shutdown(t);
601
+ }
602
+ check_read_ops(exec_ctx, &t->global);
603
+
604
+ gpr_mu_unlock(&t->mu);
605
+ GPR_TIMER_END("unlock", 0);
606
+ }
607
+
608
+ /*
609
+ * OUTPUT PROCESSING
610
+ */
611
+
612
+ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
613
+ gpr_uint32 value) {
614
+ const grpc_chttp2_setting_parameters *sp =
615
+ &grpc_chttp2_settings_parameters[id];
616
+ gpr_uint32 use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
617
+ if (use_value != value) {
618
+ gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
619
+ value, use_value);
620
+ }
621
+ if (use_value != t->global.settings[GRPC_LOCAL_SETTINGS][id]) {
622
+ t->global.settings[GRPC_LOCAL_SETTINGS][id] = use_value;
623
+ t->global.dirtied_local_settings = 1;
624
+ }
625
+ }
626
+
627
+ void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
628
+ void *transport_writing_ptr, int success) {
629
+ grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr;
630
+ grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
631
+ grpc_chttp2_stream_global *stream_global;
632
+
633
+ GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0);
634
+
635
+ lock(t);
636
+
637
+ allow_endpoint_shutdown_locked(exec_ctx, t);
638
+
639
+ if (!success) {
640
+ drop_connection(exec_ctx, t);
641
+ }
642
+
643
+ grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
644
+
645
+ while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global, &stream_global)) {
646
+ fail_pending_writes(exec_ctx, stream_global);
647
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
648
+ }
649
+
650
+ /* leave the writing flag up on shutdown to prevent further writes in unlock()
651
+ from starting */
652
+ t->writing_active = 0;
653
+ if (t->ep && !t->endpoint_reading) {
654
+ destroy_endpoint(exec_ctx, t);
655
+ }
656
+
657
+ unlock(exec_ctx, t);
658
+
659
+ UNREF_TRANSPORT(exec_ctx, t, "writing");
660
+
661
+ GPR_TIMER_END("grpc_chttp2_terminate_writing", 0);
662
+ }
663
+
664
+ static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
665
+ int iomgr_success_ignored) {
666
+ grpc_chttp2_transport *t = gt;
667
+ GPR_TIMER_BEGIN("writing_action", 0);
668
+ grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
669
+ GPR_TIMER_END("writing_action", 0);
670
+ }
671
+
672
+ void grpc_chttp2_add_incoming_goaway(
673
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
674
+ gpr_uint32 goaway_error, gpr_slice goaway_text) {
675
+ char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
676
+ gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg);
677
+ gpr_free(msg);
678
+ gpr_slice_unref(goaway_text);
679
+ transport_global->seen_goaway = 1;
680
+ connectivity_state_set(exec_ctx, transport_global, GRPC_CHANNEL_FATAL_FAILURE,
681
+ "got_goaway");
682
+ }
683
+
684
+ static void maybe_start_some_streams(
685
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) {
686
+ grpc_chttp2_stream_global *stream_global;
687
+ gpr_uint32 stream_incoming_window;
688
+ /* start streams where we have free grpc_chttp2_stream ids and free
689
+ * concurrency */
690
+ while (transport_global->next_stream_id <= MAX_CLIENT_STREAM_ID &&
691
+ transport_global->concurrent_stream_count <
692
+ transport_global
693
+ ->settings[GRPC_PEER_SETTINGS]
694
+ [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] &&
695
+ grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
696
+ &stream_global)) {
697
+ /* safe since we can't (legally) be parsing this stream yet */
698
+ grpc_chttp2_stream_parsing *stream_parsing =
699
+ &STREAM_FROM_GLOBAL(stream_global)->parsing;
700
+ GRPC_CHTTP2_IF_TRACING(gpr_log(
701
+ GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
702
+ transport_global->is_client ? "CLI" : "SVR", stream_global,
703
+ transport_global->next_stream_id));
704
+
705
+ GPR_ASSERT(stream_global->id == 0);
706
+ stream_global->id = stream_parsing->id = transport_global->next_stream_id;
707
+ transport_global->next_stream_id += 2;
708
+
709
+ if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
710
+ connectivity_state_set(exec_ctx, transport_global,
711
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
712
+ "no_more_stream_ids");
713
+ }
714
+
715
+ stream_global->outgoing_window =
716
+ transport_global->settings[GRPC_PEER_SETTINGS]
717
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
718
+ stream_parsing->incoming_window = stream_incoming_window =
719
+ transport_global->settings[GRPC_SENT_SETTINGS]
720
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
721
+ stream_global->max_recv_bytes =
722
+ GPR_MAX(stream_incoming_window, stream_global->max_recv_bytes);
723
+ grpc_chttp2_stream_map_add(
724
+ &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map,
725
+ stream_global->id, STREAM_FROM_GLOBAL(stream_global));
726
+ stream_global->in_stream_map = 1;
727
+ transport_global->concurrent_stream_count++;
728
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
729
+ }
730
+ /* cancel out streams that will never be started */
731
+ while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
732
+ grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
733
+ &stream_global)) {
734
+ cancel_from_api(exec_ctx, transport_global, stream_global,
735
+ GRPC_STATUS_UNAVAILABLE);
736
+ }
737
+ }
738
+
739
+ static grpc_closure *add_closure_barrier(grpc_closure *closure) {
740
+ closure->final_data += 2;
741
+ return closure;
742
+ }
743
+
744
+ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
745
+ grpc_closure **pclosure, int success) {
746
+ grpc_closure *closure = *pclosure;
747
+ if (closure == NULL) {
748
+ return;
749
+ }
750
+ closure->final_data -= 2;
751
+ if (!success) {
752
+ closure->final_data |= 1;
753
+ }
754
+ if (closure->final_data < 2) {
755
+ grpc_exec_ctx_enqueue(exec_ctx, closure, closure->final_data == 0);
756
+ }
757
+ *pclosure = NULL;
758
+ }
759
+
760
+ static int contains_non_ok_status(
761
+ grpc_chttp2_transport_global *transport_global,
762
+ grpc_metadata_batch *batch) {
763
+ grpc_linked_mdelem *l;
764
+ for (l = batch->list.head; l; l = l->next) {
765
+ if (l->md->key == GRPC_MDSTR_GRPC_STATUS &&
766
+ l->md != GRPC_MDELEM_GRPC_STATUS_0) {
767
+ return 1;
768
+ }
769
+ }
770
+ return 0;
771
+ }
772
+
773
+ static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, int success) {}
774
+
775
+ static void perform_stream_op_locked(
776
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
777
+ grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) {
778
+ grpc_closure *on_complete;
779
+
780
+ GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
781
+
782
+ on_complete = op->on_complete;
783
+ if (on_complete == NULL) {
784
+ on_complete = grpc_closure_create(do_nothing, NULL);
785
+ }
786
+ /* use final_data as a barrier until enqueue time; the inital counter is
787
+ dropped at the end of this function */
788
+ on_complete->final_data = 2;
789
+
790
+ if (op->cancel_with_status != GRPC_STATUS_OK) {
791
+ cancel_from_api(exec_ctx, transport_global, stream_global,
792
+ op->cancel_with_status);
793
+ }
794
+
795
+ if (op->close_with_status != GRPC_STATUS_OK) {
796
+ close_from_api(exec_ctx, transport_global, stream_global,
797
+ op->close_with_status, op->optional_close_message);
798
+ }
799
+
800
+ if (op->send_initial_metadata != NULL) {
801
+ GPR_ASSERT(stream_global->send_initial_metadata_finished == NULL);
802
+ stream_global->send_initial_metadata_finished =
803
+ add_closure_barrier(on_complete);
804
+ stream_global->send_initial_metadata = op->send_initial_metadata;
805
+ if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
806
+ stream_global->seen_error = 1;
807
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
808
+ }
809
+ if (!stream_global->write_closed) {
810
+ if (transport_global->is_client) {
811
+ GPR_ASSERT(stream_global->id == 0);
812
+ grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
813
+ stream_global);
814
+ maybe_start_some_streams(exec_ctx, transport_global);
815
+ } else {
816
+ GPR_ASSERT(stream_global->id != 0);
817
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
818
+ }
819
+ } else {
820
+ grpc_chttp2_complete_closure_step(
821
+ exec_ctx, &stream_global->send_initial_metadata_finished, 0);
822
+ }
823
+ }
824
+
825
+ if (op->send_message != NULL) {
826
+ GPR_ASSERT(stream_global->send_message_finished == NULL);
827
+ GPR_ASSERT(stream_global->send_message == NULL);
828
+ stream_global->send_message_finished = add_closure_barrier(on_complete);
829
+ if (stream_global->write_closed) {
830
+ grpc_chttp2_complete_closure_step(
831
+ exec_ctx, &stream_global->send_message_finished, 0);
832
+ } else if (stream_global->id != 0) {
833
+ stream_global->send_message = op->send_message;
834
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
835
+ }
836
+ }
837
+
838
+ if (op->send_trailing_metadata != NULL) {
839
+ GPR_ASSERT(stream_global->send_trailing_metadata_finished == NULL);
840
+ stream_global->send_trailing_metadata_finished =
841
+ add_closure_barrier(on_complete);
842
+ stream_global->send_trailing_metadata = op->send_trailing_metadata;
843
+ if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) {
844
+ stream_global->seen_error = 1;
845
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
846
+ }
847
+ if (stream_global->write_closed) {
848
+ grpc_chttp2_complete_closure_step(
849
+ exec_ctx, &stream_global->send_trailing_metadata_finished,
850
+ grpc_metadata_batch_is_empty(op->send_trailing_metadata));
851
+ } else if (stream_global->id != 0) {
852
+ /* TODO(ctiller): check if there's flow control for any outstanding
853
+ bytes before going writable */
854
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
855
+ }
856
+ }
857
+
858
+ if (op->recv_initial_metadata != NULL) {
859
+ GPR_ASSERT(stream_global->recv_initial_metadata_finished == NULL);
860
+ stream_global->recv_initial_metadata_finished =
861
+ add_closure_barrier(on_complete);
862
+ stream_global->recv_initial_metadata = op->recv_initial_metadata;
863
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
864
+ }
865
+
866
+ if (op->recv_message != NULL) {
867
+ GPR_ASSERT(stream_global->recv_message_ready == NULL);
868
+ stream_global->recv_message_ready = op->recv_message_ready;
869
+ stream_global->recv_message = op->recv_message;
870
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
871
+ }
872
+
873
+ if (op->recv_trailing_metadata != NULL) {
874
+ GPR_ASSERT(stream_global->recv_trailing_metadata_finished == NULL);
875
+ stream_global->recv_trailing_metadata_finished =
876
+ add_closure_barrier(on_complete);
877
+ stream_global->recv_trailing_metadata = op->recv_trailing_metadata;
878
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
879
+ }
880
+
881
+ grpc_chttp2_complete_closure_step(exec_ctx, &on_complete, 1);
882
+
883
+ GPR_TIMER_END("perform_stream_op_locked", 0);
884
+ }
885
+
886
+ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
887
+ grpc_stream *gs, grpc_transport_stream_op *op) {
888
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
889
+ grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
890
+
891
+ lock(t);
892
+ perform_stream_op_locked(exec_ctx, &t->global, &s->global, op);
893
+ unlock(exec_ctx, t);
894
+ }
895
+
896
+ static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) {
897
+ grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
898
+ p->next = &t->global.pings;
899
+ p->prev = p->next->prev;
900
+ p->prev->next = p->next->prev = p;
901
+ p->id[0] = (gpr_uint8)((t->global.ping_counter >> 56) & 0xff);
902
+ p->id[1] = (gpr_uint8)((t->global.ping_counter >> 48) & 0xff);
903
+ p->id[2] = (gpr_uint8)((t->global.ping_counter >> 40) & 0xff);
904
+ p->id[3] = (gpr_uint8)((t->global.ping_counter >> 32) & 0xff);
905
+ p->id[4] = (gpr_uint8)((t->global.ping_counter >> 24) & 0xff);
906
+ p->id[5] = (gpr_uint8)((t->global.ping_counter >> 16) & 0xff);
907
+ p->id[6] = (gpr_uint8)((t->global.ping_counter >> 8) & 0xff);
908
+ p->id[7] = (gpr_uint8)(t->global.ping_counter & 0xff);
909
+ p->on_recv = on_recv;
910
+ gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id));
911
+ }
912
+
913
+ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
914
+ grpc_chttp2_transport_parsing *transport_parsing,
915
+ const gpr_uint8 *opaque_8bytes) {
916
+ grpc_chttp2_outstanding_ping *ping;
917
+ grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
918
+ grpc_chttp2_transport_global *transport_global = &t->global;
919
+ lock(t);
920
+ for (ping = transport_global->pings.next; ping != &transport_global->pings;
921
+ ping = ping->next) {
922
+ if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
923
+ grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, 1);
924
+ ping->next->prev = ping->prev;
925
+ ping->prev->next = ping->next;
926
+ gpr_free(ping);
927
+ break;
928
+ }
929
+ }
930
+ unlock(exec_ctx, t);
931
+ }
932
+
933
+ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
934
+ grpc_transport_op *op) {
935
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
936
+ int close_transport = 0;
937
+
938
+ lock(t);
939
+
940
+ grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
941
+
942
+ if (op->on_connectivity_state_change != NULL) {
943
+ grpc_connectivity_state_notify_on_state_change(
944
+ exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state,
945
+ op->on_connectivity_state_change);
946
+ }
947
+
948
+ if (op->send_goaway) {
949
+ t->global.sent_goaway = 1;
950
+ grpc_chttp2_goaway_append(
951
+ t->global.last_incoming_stream_id,
952
+ (gpr_uint32)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
953
+ gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
954
+ close_transport = !grpc_chttp2_has_streams(t);
955
+ }
956
+
957
+ if (op->set_accept_stream != NULL) {
958
+ t->channel_callback.accept_stream = op->set_accept_stream;
959
+ t->channel_callback.accept_stream_user_data =
960
+ op->set_accept_stream_user_data;
961
+ }
962
+
963
+ if (op->bind_pollset) {
964
+ add_to_pollset_locked(exec_ctx, t, op->bind_pollset);
965
+ }
966
+
967
+ if (op->bind_pollset_set) {
968
+ add_to_pollset_set_locked(exec_ctx, t, op->bind_pollset_set);
969
+ }
970
+
971
+ if (op->send_ping) {
972
+ send_ping_locked(t, op->send_ping);
973
+ }
974
+
975
+ if (op->disconnect) {
976
+ close_transport_locked(exec_ctx, t);
977
+ }
978
+
979
+ unlock(exec_ctx, t);
980
+
981
+ if (close_transport) {
982
+ lock(t);
983
+ close_transport_locked(exec_ctx, t);
984
+ unlock(exec_ctx, t);
985
+ }
986
+ }
987
+
988
+ /*
989
+ * INPUT PROCESSING
990
+ */
991
+
992
+ static void check_read_ops(grpc_exec_ctx *exec_ctx,
993
+ grpc_chttp2_transport_global *transport_global) {
994
+ grpc_chttp2_stream_global *stream_global;
995
+ grpc_byte_stream *bs;
996
+ while (
997
+ grpc_chttp2_list_pop_check_read_ops(transport_global, &stream_global)) {
998
+ if (stream_global->recv_initial_metadata_finished != NULL &&
999
+ stream_global->published_initial_metadata) {
1000
+ grpc_chttp2_incoming_metadata_buffer_publish(
1001
+ &stream_global->received_initial_metadata,
1002
+ stream_global->recv_initial_metadata);
1003
+ grpc_chttp2_complete_closure_step(
1004
+ exec_ctx, &stream_global->recv_initial_metadata_finished, 1);
1005
+ }
1006
+ if (stream_global->recv_message_ready != NULL) {
1007
+ if (stream_global->incoming_frames.head != NULL) {
1008
+ *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
1009
+ &stream_global->incoming_frames);
1010
+ GPR_ASSERT(*stream_global->recv_message != NULL);
1011
+ grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, 1);
1012
+ stream_global->recv_message_ready = NULL;
1013
+ } else if (stream_global->published_trailing_metadata) {
1014
+ *stream_global->recv_message = NULL;
1015
+ grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, 1);
1016
+ stream_global->recv_message_ready = NULL;
1017
+ }
1018
+ }
1019
+ if (stream_global->recv_trailing_metadata_finished != NULL &&
1020
+ stream_global->read_closed && stream_global->write_closed) {
1021
+ while (stream_global->seen_error &&
1022
+ (bs = grpc_chttp2_incoming_frame_queue_pop(
1023
+ &stream_global->incoming_frames)) != NULL) {
1024
+ grpc_byte_stream_destroy(bs);
1025
+ }
1026
+ if (stream_global->incoming_frames.head == NULL) {
1027
+ grpc_chttp2_incoming_metadata_buffer_publish(
1028
+ &stream_global->received_trailing_metadata,
1029
+ stream_global->recv_trailing_metadata);
1030
+ grpc_chttp2_complete_closure_step(
1031
+ exec_ctx, &stream_global->recv_trailing_metadata_finished, 1);
1032
+ }
1033
+ }
1034
+ }
1035
+ }
1036
+
1037
+ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1038
+ gpr_uint32 id) {
1039
+ size_t new_stream_count;
1040
+ grpc_chttp2_stream *s =
1041
+ grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
1042
+ if (!s) {
1043
+ s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
1044
+ }
1045
+ grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
1046
+ GPR_ASSERT(s);
1047
+ s->global.in_stream_map = 0;
1048
+ if (t->parsing.incoming_stream == &s->parsing) {
1049
+ t->parsing.incoming_stream = NULL;
1050
+ grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing);
1051
+ }
1052
+ if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
1053
+ close_transport_locked(exec_ctx, t);
1054
+ }
1055
+
1056
+ new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
1057
+ grpc_chttp2_stream_map_size(&t->new_stream_map);
1058
+ GPR_ASSERT(new_stream_count <= GPR_UINT32_MAX);
1059
+ if (new_stream_count != t->global.concurrent_stream_count) {
1060
+ t->global.concurrent_stream_count = (gpr_uint32)new_stream_count;
1061
+ maybe_start_some_streams(exec_ctx, &t->global);
1062
+ }
1063
+ }
1064
+
1065
+ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
1066
+ grpc_chttp2_transport_global *transport_global,
1067
+ grpc_chttp2_stream_global *stream_global,
1068
+ grpc_status_code status) {
1069
+ if (stream_global->id != 0) {
1070
+ gpr_slice_buffer_add(
1071
+ &transport_global->qbuf,
1072
+ grpc_chttp2_rst_stream_create(
1073
+ stream_global->id,
1074
+ (gpr_uint32)grpc_chttp2_grpc_status_to_http2_error(status)));
1075
+ }
1076
+ grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
1077
+ NULL);
1078
+ grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1079
+ 1);
1080
+ }
1081
+
1082
+ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
1083
+ grpc_chttp2_transport_global *transport_global,
1084
+ grpc_chttp2_stream_global *stream_global,
1085
+ grpc_status_code status, gpr_slice *slice) {
1086
+ if (status != GRPC_STATUS_OK) {
1087
+ stream_global->seen_error = 1;
1088
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1089
+ }
1090
+ /* stream_global->recv_trailing_metadata_finished gives us a
1091
+ last chance replacement: we've received trailing metadata,
1092
+ but something more important has become available to signal
1093
+ to the upper layers - drop what we've got, and then publish
1094
+ what we want - which is safe because we haven't told anyone
1095
+ about the metadata yet */
1096
+ if (!stream_global->published_trailing_metadata ||
1097
+ stream_global->recv_trailing_metadata_finished != NULL) {
1098
+ char status_string[GPR_LTOA_MIN_BUFSIZE];
1099
+ gpr_ltoa(status, status_string);
1100
+ grpc_chttp2_incoming_metadata_buffer_add(
1101
+ &stream_global->received_trailing_metadata,
1102
+ grpc_mdelem_from_metadata_strings(
1103
+ GRPC_MDSTR_GRPC_STATUS, grpc_mdstr_from_string(status_string)));
1104
+ if (slice) {
1105
+ grpc_chttp2_incoming_metadata_buffer_add(
1106
+ &stream_global->received_trailing_metadata,
1107
+ grpc_mdelem_from_metadata_strings(
1108
+ GRPC_MDSTR_GRPC_MESSAGE,
1109
+ grpc_mdstr_from_slice(gpr_slice_ref(*slice))));
1110
+ }
1111
+ stream_global->published_trailing_metadata = 1;
1112
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1113
+ }
1114
+ if (slice) {
1115
+ gpr_slice_unref(*slice);
1116
+ }
1117
+ }
1118
+
1119
+ static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
1120
+ grpc_chttp2_stream_global *stream_global) {
1121
+ grpc_chttp2_complete_closure_step(
1122
+ exec_ctx, &stream_global->send_initial_metadata_finished, 0);
1123
+ grpc_chttp2_complete_closure_step(
1124
+ exec_ctx, &stream_global->send_trailing_metadata_finished, 0);
1125
+ grpc_chttp2_complete_closure_step(exec_ctx,
1126
+ &stream_global->send_message_finished, 0);
1127
+ }
1128
+
1129
+ void grpc_chttp2_mark_stream_closed(
1130
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
1131
+ grpc_chttp2_stream_global *stream_global, int close_reads,
1132
+ int close_writes) {
1133
+ if (stream_global->read_closed && stream_global->write_closed) {
1134
+ /* already closed */
1135
+ return;
1136
+ }
1137
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1138
+ if (close_reads && !stream_global->read_closed) {
1139
+ stream_global->read_closed = 1;
1140
+ stream_global->published_initial_metadata = 1;
1141
+ stream_global->published_trailing_metadata = 1;
1142
+ }
1143
+ if (close_writes && !stream_global->write_closed) {
1144
+ stream_global->write_closed = 1;
1145
+ if (TRANSPORT_FROM_GLOBAL(transport_global)->writing_active) {
1146
+ GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes");
1147
+ grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
1148
+ stream_global);
1149
+ } else {
1150
+ fail_pending_writes(exec_ctx, stream_global);
1151
+ }
1152
+ }
1153
+ if (stream_global->read_closed && stream_global->write_closed) {
1154
+ if (stream_global->id != 0 &&
1155
+ TRANSPORT_FROM_GLOBAL(transport_global)->parsing_active) {
1156
+ grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
1157
+ stream_global);
1158
+ } else {
1159
+ if (stream_global->id != 0) {
1160
+ remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
1161
+ stream_global->id);
1162
+ }
1163
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
1164
+ }
1165
+ }
1166
+ }
1167
+
1168
+ static void close_from_api(grpc_exec_ctx *exec_ctx,
1169
+ grpc_chttp2_transport_global *transport_global,
1170
+ grpc_chttp2_stream_global *stream_global,
1171
+ grpc_status_code status,
1172
+ gpr_slice *optional_message) {
1173
+ gpr_slice hdr;
1174
+ gpr_slice status_hdr;
1175
+ gpr_slice message_pfx;
1176
+ gpr_uint8 *p;
1177
+ gpr_uint32 len = 0;
1178
+
1179
+ GPR_ASSERT(status >= 0 && (int)status < 100);
1180
+
1181
+ GPR_ASSERT(stream_global->id != 0);
1182
+
1183
+ /* Hand roll a header block.
1184
+ This is unnecessarily ugly - at some point we should find a more elegant
1185
+ solution.
1186
+ It's complicated by the fact that our send machinery would be dead by the
1187
+ time we got around to sending this, so instead we ignore HPACK compression
1188
+ and just write the uncompressed bytes onto the wire. */
1189
+ status_hdr = gpr_slice_malloc(15 + (status >= 10));
1190
+ p = GPR_SLICE_START_PTR(status_hdr);
1191
+ *p++ = 0x40; /* literal header */
1192
+ *p++ = 11; /* len(grpc-status) */
1193
+ *p++ = 'g';
1194
+ *p++ = 'r';
1195
+ *p++ = 'p';
1196
+ *p++ = 'c';
1197
+ *p++ = '-';
1198
+ *p++ = 's';
1199
+ *p++ = 't';
1200
+ *p++ = 'a';
1201
+ *p++ = 't';
1202
+ *p++ = 'u';
1203
+ *p++ = 's';
1204
+ if (status < 10) {
1205
+ *p++ = 1;
1206
+ *p++ = (gpr_uint8)('0' + status);
1207
+ } else {
1208
+ *p++ = 2;
1209
+ *p++ = (gpr_uint8)('0' + (status / 10));
1210
+ *p++ = (gpr_uint8)('0' + (status % 10));
1211
+ }
1212
+ GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
1213
+ len += (gpr_uint32)GPR_SLICE_LENGTH(status_hdr);
1214
+
1215
+ if (optional_message) {
1216
+ GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127);
1217
+ message_pfx = gpr_slice_malloc(15);
1218
+ p = GPR_SLICE_START_PTR(message_pfx);
1219
+ *p++ = 0x40;
1220
+ *p++ = 12; /* len(grpc-message) */
1221
+ *p++ = 'g';
1222
+ *p++ = 'r';
1223
+ *p++ = 'p';
1224
+ *p++ = 'c';
1225
+ *p++ = '-';
1226
+ *p++ = 'm';
1227
+ *p++ = 'e';
1228
+ *p++ = 's';
1229
+ *p++ = 's';
1230
+ *p++ = 'a';
1231
+ *p++ = 'g';
1232
+ *p++ = 'e';
1233
+ *p++ = (gpr_uint8)GPR_SLICE_LENGTH(*optional_message);
1234
+ GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
1235
+ len += (gpr_uint32)GPR_SLICE_LENGTH(message_pfx);
1236
+ len += (gpr_uint32)GPR_SLICE_LENGTH(*optional_message);
1237
+ }
1238
+
1239
+ hdr = gpr_slice_malloc(9);
1240
+ p = GPR_SLICE_START_PTR(hdr);
1241
+ *p++ = (gpr_uint8)(len >> 16);
1242
+ *p++ = (gpr_uint8)(len >> 8);
1243
+ *p++ = (gpr_uint8)(len);
1244
+ *p++ = GRPC_CHTTP2_FRAME_HEADER;
1245
+ *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
1246
+ *p++ = (gpr_uint8)(stream_global->id >> 24);
1247
+ *p++ = (gpr_uint8)(stream_global->id >> 16);
1248
+ *p++ = (gpr_uint8)(stream_global->id >> 8);
1249
+ *p++ = (gpr_uint8)(stream_global->id);
1250
+ GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr));
1251
+
1252
+ gpr_slice_buffer_add(&transport_global->qbuf, hdr);
1253
+ gpr_slice_buffer_add(&transport_global->qbuf, status_hdr);
1254
+ if (optional_message) {
1255
+ gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
1256
+ gpr_slice_buffer_add(&transport_global->qbuf,
1257
+ gpr_slice_ref(*optional_message));
1258
+ }
1259
+
1260
+ gpr_slice_buffer_add(
1261
+ &transport_global->qbuf,
1262
+ grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR));
1263
+
1264
+ if (optional_message) {
1265
+ gpr_slice_ref(*optional_message);
1266
+ }
1267
+ grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
1268
+ optional_message);
1269
+ grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1270
+ 1);
1271
+ }
1272
+
1273
+ static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
1274
+ void *user_data,
1275
+ grpc_chttp2_stream_global *stream_global) {
1276
+ cancel_from_api(user_data, transport_global, stream_global,
1277
+ GRPC_STATUS_UNAVAILABLE);
1278
+ }
1279
+
1280
+ static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
1281
+ grpc_chttp2_transport *t) {
1282
+ grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb);
1283
+ }
1284
+
1285
+ static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
1286
+ close_transport_locked(exec_ctx, t);
1287
+ end_all_the_calls(exec_ctx, t);
1288
+ }
1289
+
1290
+ /** update window from a settings change */
1291
+ static void update_global_window(void *args, gpr_uint32 id, void *stream) {
1292
+ grpc_chttp2_transport *t = args;
1293
+ grpc_chttp2_stream *s = stream;
1294
+ grpc_chttp2_transport_global *transport_global = &t->global;
1295
+ grpc_chttp2_stream_global *stream_global = &s->global;
1296
+ int was_zero;
1297
+ int is_zero;
1298
+ gpr_int64 initial_window_update = t->parsing.initial_window_update;
1299
+
1300
+ was_zero = stream_global->outgoing_window <= 0;
1301
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", transport_global, stream_global,
1302
+ outgoing_window, initial_window_update);
1303
+ is_zero = stream_global->outgoing_window <= 0;
1304
+
1305
+ if (was_zero && !is_zero) {
1306
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
1307
+ }
1308
+ }
1309
+
1310
+ static void read_error_locked(grpc_exec_ctx *exec_ctx,
1311
+ grpc_chttp2_transport *t) {
1312
+ t->endpoint_reading = 0;
1313
+ if (!t->writing_active && t->ep) {
1314
+ destroy_endpoint(exec_ctx, t);
1315
+ }
1316
+ }
1317
+
1318
+ /* tcp read callback */
1319
+ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, int success) {
1320
+ size_t i;
1321
+ int keep_reading = 0;
1322
+ grpc_chttp2_transport *t = tp;
1323
+ grpc_chttp2_transport_global *transport_global = &t->global;
1324
+ grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
1325
+ grpc_chttp2_stream_global *stream_global;
1326
+
1327
+ GPR_TIMER_BEGIN("recv_data", 0);
1328
+
1329
+ lock(t);
1330
+ i = 0;
1331
+ GPR_ASSERT(!t->parsing_active);
1332
+ if (!t->closed) {
1333
+ t->parsing_active = 1;
1334
+ /* merge stream lists */
1335
+ grpc_chttp2_stream_map_move_into(&t->new_stream_map,
1336
+ &t->parsing_stream_map);
1337
+ grpc_chttp2_prepare_to_read(transport_global, transport_parsing);
1338
+ gpr_mu_unlock(&t->mu);
1339
+ GPR_TIMER_BEGIN("recv_data.parse", 0);
1340
+ for (; i < t->read_buffer.count &&
1341
+ grpc_chttp2_perform_read(exec_ctx, transport_parsing,
1342
+ t->read_buffer.slices[i]);
1343
+ i++)
1344
+ ;
1345
+ GPR_TIMER_END("recv_data.parse", 0);
1346
+ gpr_mu_lock(&t->mu);
1347
+ /* copy parsing qbuf to global qbuf */
1348
+ gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf);
1349
+ if (i != t->read_buffer.count) {
1350
+ unlock(exec_ctx, t);
1351
+ lock(t);
1352
+ drop_connection(exec_ctx, t);
1353
+ }
1354
+ /* merge stream lists */
1355
+ grpc_chttp2_stream_map_move_into(&t->new_stream_map,
1356
+ &t->parsing_stream_map);
1357
+ transport_global->concurrent_stream_count =
1358
+ (gpr_uint32)grpc_chttp2_stream_map_size(&t->parsing_stream_map);
1359
+ if (transport_parsing->initial_window_update != 0) {
1360
+ grpc_chttp2_stream_map_for_each(&t->parsing_stream_map,
1361
+ update_global_window, t);
1362
+ transport_parsing->initial_window_update = 0;
1363
+ }
1364
+ /* handle higher level things */
1365
+ grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing);
1366
+ t->parsing_active = 0;
1367
+ /* if a stream is in the stream map, and gets cancelled, we need to ensure
1368
+ * we are not parsing before continuing the cancellation to keep things in
1369
+ * a sane state */
1370
+ while (grpc_chttp2_list_pop_closed_waiting_for_parsing(transport_global,
1371
+ &stream_global)) {
1372
+ GPR_ASSERT(stream_global->in_stream_map);
1373
+ GPR_ASSERT(stream_global->write_closed);
1374
+ GPR_ASSERT(stream_global->read_closed);
1375
+ remove_stream(exec_ctx, t, stream_global->id);
1376
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
1377
+ }
1378
+ }
1379
+ if (!success || i != t->read_buffer.count || t->closed) {
1380
+ drop_connection(exec_ctx, t);
1381
+ read_error_locked(exec_ctx, t);
1382
+ } else if (!t->closed) {
1383
+ keep_reading = 1;
1384
+ REF_TRANSPORT(t, "keep_reading");
1385
+ prevent_endpoint_shutdown(t);
1386
+ }
1387
+ gpr_slice_buffer_reset_and_unref(&t->read_buffer);
1388
+ unlock(exec_ctx, t);
1389
+
1390
+ if (keep_reading) {
1391
+ grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->recv_data);
1392
+ allow_endpoint_shutdown_unlocked(exec_ctx, t);
1393
+ UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
1394
+ } else {
1395
+ UNREF_TRANSPORT(exec_ctx, t, "recv_data");
1396
+ }
1397
+
1398
+ GPR_TIMER_END("recv_data", 0);
1399
+ }
1400
+
1401
+ /*
1402
+ * CALLBACK LOOP
1403
+ */
1404
+
1405
+ static void connectivity_state_set(
1406
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
1407
+ grpc_connectivity_state state, const char *reason) {
1408
+ GRPC_CHTTP2_IF_TRACING(
1409
+ gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
1410
+ grpc_connectivity_state_set(exec_ctx, &TRANSPORT_FROM_GLOBAL(transport_global)
1411
+ ->channel_callback.state_tracker,
1412
+ state, reason);
1413
+ }
1414
+
1415
+ /*
1416
+ * POLLSET STUFF
1417
+ */
1418
+
1419
+ static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
1420
+ grpc_chttp2_transport *t,
1421
+ grpc_pollset *pollset) {
1422
+ if (t->ep) {
1423
+ grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset);
1424
+ }
1425
+ }
1426
+
1427
+ static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
1428
+ grpc_chttp2_transport *t,
1429
+ grpc_pollset_set *pollset_set) {
1430
+ if (t->ep) {
1431
+ grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set);
1432
+ }
1433
+ }
1434
+
1435
+ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1436
+ grpc_stream *gs, grpc_pollset *pollset) {
1437
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
1438
+ lock(t);
1439
+ add_to_pollset_locked(exec_ctx, t, pollset);
1440
+ unlock(exec_ctx, t);
1441
+ }
1442
+
1443
+ /*
1444
+ * BYTE STREAM
1445
+ */
1446
+
1447
+ static void incoming_byte_stream_update_flow_control(
1448
+ grpc_chttp2_transport_global *transport_global,
1449
+ grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
1450
+ size_t have_already) {
1451
+ gpr_uint32 max_recv_bytes;
1452
+
1453
+ /* clamp max recv hint to an allowable size */
1454
+ if (max_size_hint >= GPR_UINT32_MAX - transport_global->stream_lookahead) {
1455
+ max_recv_bytes = GPR_UINT32_MAX - transport_global->stream_lookahead;
1456
+ } else {
1457
+ max_recv_bytes = (gpr_uint32)max_size_hint;
1458
+ }
1459
+
1460
+ /* account for bytes already received but unknown to higher layers */
1461
+ if (max_recv_bytes >= have_already) {
1462
+ max_recv_bytes -= (gpr_uint32)have_already;
1463
+ } else {
1464
+ max_recv_bytes = 0;
1465
+ }
1466
+
1467
+ /* add some small lookahead to keep pipelines flowing */
1468
+ GPR_ASSERT(max_recv_bytes <=
1469
+ GPR_UINT32_MAX - transport_global->stream_lookahead);
1470
+ max_recv_bytes += transport_global->stream_lookahead;
1471
+ if (stream_global->max_recv_bytes < max_recv_bytes) {
1472
+ gpr_uint32 add_max_recv_bytes =
1473
+ max_recv_bytes - stream_global->max_recv_bytes;
1474
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
1475
+ max_recv_bytes, add_max_recv_bytes);
1476
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
1477
+ unannounced_incoming_window_for_parse,
1478
+ add_max_recv_bytes);
1479
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
1480
+ unannounced_incoming_window_for_writing,
1481
+ add_max_recv_bytes);
1482
+ grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
1483
+ stream_global);
1484
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
1485
+ }
1486
+ }
1487
+
1488
+ static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx,
1489
+ grpc_byte_stream *byte_stream,
1490
+ gpr_slice *slice, size_t max_size_hint,
1491
+ grpc_closure *on_complete) {
1492
+ grpc_chttp2_incoming_byte_stream *bs =
1493
+ (grpc_chttp2_incoming_byte_stream *)byte_stream;
1494
+ grpc_chttp2_transport_global *transport_global = &bs->transport->global;
1495
+ grpc_chttp2_stream_global *stream_global = &bs->stream->global;
1496
+
1497
+ lock(bs->transport);
1498
+ if (bs->is_tail) {
1499
+ incoming_byte_stream_update_flow_control(transport_global, stream_global,
1500
+ max_size_hint, bs->slices.length);
1501
+ }
1502
+ if (bs->slices.count > 0) {
1503
+ *slice = gpr_slice_buffer_take_first(&bs->slices);
1504
+ unlock(exec_ctx, bs->transport);
1505
+ return 1;
1506
+ } else {
1507
+ bs->on_next = on_complete;
1508
+ bs->next = slice;
1509
+ unlock(exec_ctx, bs->transport);
1510
+ return 0;
1511
+ }
1512
+ }
1513
+
1514
+ static void incoming_byte_stream_unref(grpc_chttp2_incoming_byte_stream *bs) {
1515
+ if (gpr_unref(&bs->refs)) {
1516
+ gpr_slice_buffer_destroy(&bs->slices);
1517
+ gpr_free(bs);
1518
+ }
1519
+ }
1520
+
1521
+ static void incoming_byte_stream_destroy(grpc_byte_stream *byte_stream) {
1522
+ incoming_byte_stream_unref((grpc_chttp2_incoming_byte_stream *)byte_stream);
1523
+ }
1524
+
1525
+ void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
1526
+ grpc_chttp2_incoming_byte_stream *bs,
1527
+ gpr_slice slice) {
1528
+ gpr_mu_lock(&bs->transport->mu);
1529
+ if (bs->on_next != NULL) {
1530
+ *bs->next = slice;
1531
+ grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, 1);
1532
+ bs->on_next = NULL;
1533
+ } else {
1534
+ gpr_slice_buffer_add(&bs->slices, slice);
1535
+ }
1536
+ gpr_mu_unlock(&bs->transport->mu);
1537
+ }
1538
+
1539
+ void grpc_chttp2_incoming_byte_stream_finished(
1540
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs) {
1541
+ incoming_byte_stream_unref(bs);
1542
+ }
1543
+
1544
+ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
1545
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
1546
+ grpc_chttp2_stream_parsing *stream_parsing, gpr_uint32 frame_size,
1547
+ gpr_uint32 flags, grpc_chttp2_incoming_frame_queue *add_to_queue) {
1548
+ grpc_chttp2_incoming_byte_stream *incoming_byte_stream =
1549
+ gpr_malloc(sizeof(*incoming_byte_stream));
1550
+ incoming_byte_stream->base.length = frame_size;
1551
+ incoming_byte_stream->base.flags = flags;
1552
+ incoming_byte_stream->base.next = incoming_byte_stream_next;
1553
+ incoming_byte_stream->base.destroy = incoming_byte_stream_destroy;
1554
+ gpr_ref_init(&incoming_byte_stream->refs, 2);
1555
+ incoming_byte_stream->next_message = NULL;
1556
+ incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing);
1557
+ incoming_byte_stream->stream = STREAM_FROM_PARSING(stream_parsing);
1558
+ gpr_slice_buffer_init(&incoming_byte_stream->slices);
1559
+ incoming_byte_stream->on_next = NULL;
1560
+ incoming_byte_stream->is_tail = 1;
1561
+ if (add_to_queue->head == NULL) {
1562
+ add_to_queue->head = incoming_byte_stream;
1563
+ } else {
1564
+ add_to_queue->tail->is_tail = 0;
1565
+ add_to_queue->tail->next_message = incoming_byte_stream;
1566
+ }
1567
+ add_to_queue->tail = incoming_byte_stream;
1568
+ if (frame_size == 0) {
1569
+ lock(TRANSPORT_FROM_PARSING(transport_parsing));
1570
+ incoming_byte_stream_update_flow_control(
1571
+ &TRANSPORT_FROM_PARSING(transport_parsing)->global,
1572
+ &STREAM_FROM_PARSING(stream_parsing)->global, 0, 0);
1573
+ unlock(exec_ctx, TRANSPORT_FROM_PARSING(transport_parsing));
1574
+ }
1575
+ return incoming_byte_stream;
1576
+ }
1577
+
1578
+ /*
1579
+ * TRACING
1580
+ */
1581
+
1582
+ static char *format_flowctl_context_var(const char *context, const char *var,
1583
+ gpr_int64 val, gpr_uint32 id,
1584
+ char **scope) {
1585
+ char *underscore_pos;
1586
+ char *result;
1587
+ if (context == NULL) {
1588
+ *scope = NULL;
1589
+ gpr_asprintf(&result, "%s(%lld)", var, val);
1590
+ return result;
1591
+ }
1592
+ underscore_pos = strchr(context, '_');
1593
+ *scope = gpr_strdup(context);
1594
+ (*scope)[underscore_pos - context] = 0;
1595
+ if (id != 0) {
1596
+ char *tmp = *scope;
1597
+ gpr_asprintf(scope, "%s[%d]", tmp, id);
1598
+ gpr_free(tmp);
1599
+ }
1600
+ gpr_asprintf(&result, "%s.%s(%lld)", underscore_pos + 1, var, val);
1601
+ return result;
1602
+ }
1603
+
1604
+ static int samestr(char *a, char *b) {
1605
+ if (a == NULL) {
1606
+ return b == NULL;
1607
+ }
1608
+ if (b == NULL) {
1609
+ return 0;
1610
+ }
1611
+ return 0 == strcmp(a, b);
1612
+ }
1613
+
1614
+ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
1615
+ grpc_chttp2_flowctl_op op, const char *context1,
1616
+ const char *var1, const char *context2,
1617
+ const char *var2, int is_client,
1618
+ gpr_uint32 stream_id, gpr_int64 val1,
1619
+ gpr_int64 val2) {
1620
+ char *scope1;
1621
+ char *scope2;
1622
+ char *label1 =
1623
+ format_flowctl_context_var(context1, var1, val1, stream_id, &scope1);
1624
+ char *label2 =
1625
+ format_flowctl_context_var(context2, var2, val2, stream_id, &scope2);
1626
+ char *clisvr = is_client ? "client" : "server";
1627
+ char *prefix;
1628
+
1629
+ gpr_asprintf(&prefix, "FLOW % 8s: %s % 11s ", phase, clisvr, scope1);
1630
+
1631
+ switch (op) {
1632
+ case GRPC_CHTTP2_FLOWCTL_MOVE:
1633
+ GPR_ASSERT(samestr(scope1, scope2));
1634
+ if (val2 != 0) {
1635
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1636
+ "%sMOVE % 40s <- % 40s giving %d", prefix, label1, label2,
1637
+ val1 + val2);
1638
+ }
1639
+ break;
1640
+ case GRPC_CHTTP2_FLOWCTL_CREDIT:
1641
+ GPR_ASSERT(val2 >= 0);
1642
+ if (val2 != 0) {
1643
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1644
+ "%sCREDIT % 40s by % 40s giving %d", prefix, label1, label2,
1645
+ val1 + val2);
1646
+ }
1647
+ break;
1648
+ case GRPC_CHTTP2_FLOWCTL_DEBIT:
1649
+ GPR_ASSERT(val2 >= 0);
1650
+ if (val2 != 0) {
1651
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1652
+ "%sDEBIT % 40s by % 40s giving %d", prefix, label1, label2,
1653
+ val1 - val2);
1654
+ }
1655
+ break;
1656
+ }
1657
+
1658
+ gpr_free(scope1);
1659
+ gpr_free(scope2);
1660
+ gpr_free(label1);
1661
+ gpr_free(label2);
1662
+ gpr_free(prefix);
1663
+ }
1664
+
1665
+ /*
1666
+ * INTEGRATION GLUE
1667
+ */
1668
+
1669
+ static char *chttp2_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
1670
+ return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
1671
+ }
1672
+
1673
+ static const grpc_transport_vtable vtable = {
1674
+ sizeof(grpc_chttp2_stream), init_stream, set_pollset, perform_stream_op,
1675
+ perform_transport_op, destroy_stream, destroy_transport, chttp2_get_peer};
1676
+
1677
+ grpc_transport *grpc_create_chttp2_transport(
1678
+ grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
1679
+ grpc_endpoint *ep, int is_client) {
1680
+ grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
1681
+ init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
1682
+ return &t->base;
1683
+ }
1684
+
1685
+ void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
1686
+ grpc_transport *transport,
1687
+ gpr_slice *slices, size_t nslices) {
1688
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
1689
+ REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */
1690
+ gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
1691
+ recv_data(exec_ctx, t, 1);
1692
+ }