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,123 @@
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 <string.h>
35
+ #include <grpc/byte_buffer_reader.h>
36
+
37
+ #include <grpc/compression.h>
38
+ #include <grpc/grpc.h>
39
+ #include <grpc/support/alloc.h>
40
+ #include <grpc/support/log.h>
41
+ #include <grpc/support/slice_buffer.h>
42
+ #include <grpc/byte_buffer.h>
43
+
44
+ #include "src/core/compression/message_compress.h"
45
+
46
+ static int is_compressed(grpc_byte_buffer *buffer) {
47
+ switch (buffer->type) {
48
+ case GRPC_BB_RAW:
49
+ if (buffer->data.raw.compression == GRPC_COMPRESS_NONE) {
50
+ return 0 /* GPR_FALSE */;
51
+ }
52
+ break;
53
+ }
54
+ return 1 /* GPR_TRUE */;
55
+ }
56
+
57
+ void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
58
+ grpc_byte_buffer *buffer) {
59
+ gpr_slice_buffer decompressed_slices_buffer;
60
+ reader->buffer_in = buffer;
61
+ switch (reader->buffer_in->type) {
62
+ case GRPC_BB_RAW:
63
+ gpr_slice_buffer_init(&decompressed_slices_buffer);
64
+ if (is_compressed(reader->buffer_in)) {
65
+ grpc_msg_decompress(reader->buffer_in->data.raw.compression,
66
+ &reader->buffer_in->data.raw.slice_buffer,
67
+ &decompressed_slices_buffer);
68
+ reader->buffer_out =
69
+ grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices,
70
+ decompressed_slices_buffer.count);
71
+ gpr_slice_buffer_destroy(&decompressed_slices_buffer);
72
+ } else { /* not compressed, use the input buffer as output */
73
+ reader->buffer_out = reader->buffer_in;
74
+ }
75
+ reader->current.index = 0;
76
+ break;
77
+ }
78
+ }
79
+
80
+ void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) {
81
+ switch (reader->buffer_in->type) {
82
+ case GRPC_BB_RAW:
83
+ /* keeping the same if-else structure as in the init function */
84
+ if (is_compressed(reader->buffer_in)) {
85
+ grpc_byte_buffer_destroy(reader->buffer_out);
86
+ }
87
+ break;
88
+ }
89
+ }
90
+
91
+ int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
92
+ gpr_slice *slice) {
93
+ switch (reader->buffer_in->type) {
94
+ case GRPC_BB_RAW: {
95
+ gpr_slice_buffer *slice_buffer;
96
+ slice_buffer = &reader->buffer_out->data.raw.slice_buffer;
97
+ if (reader->current.index < slice_buffer->count) {
98
+ *slice = gpr_slice_ref(slice_buffer->slices[reader->current.index]);
99
+ reader->current.index += 1;
100
+ return 1;
101
+ }
102
+ break;
103
+ }
104
+ }
105
+ return 0;
106
+ }
107
+
108
+ gpr_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) {
109
+ gpr_slice in_slice;
110
+ size_t bytes_read = 0;
111
+ const size_t input_size = grpc_byte_buffer_length(reader->buffer_out);
112
+ gpr_slice out_slice = gpr_slice_malloc(input_size);
113
+ gpr_uint8 *const outbuf = GPR_SLICE_START_PTR(out_slice); /* just an alias */
114
+
115
+ while (grpc_byte_buffer_reader_next(reader, &in_slice) != 0) {
116
+ const size_t slice_length = GPR_SLICE_LENGTH(in_slice);
117
+ memcpy(&(outbuf[bytes_read]), GPR_SLICE_START_PTR(in_slice), slice_length);
118
+ bytes_read += slice_length;
119
+ gpr_slice_unref(in_slice);
120
+ GPR_ASSERT(bytes_read <= input_size);
121
+ }
122
+ return out_slice;
123
+ }
@@ -0,0 +1,1424 @@
1
+ /*
2
+ *
3
+ * Copyright 2015-2016, 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
+ #include <assert.h>
34
+ #include <limits.h>
35
+ #include <stdio.h>
36
+ #include <stdlib.h>
37
+ #include <string.h>
38
+
39
+ #include <grpc/compression.h>
40
+ #include <grpc/grpc.h>
41
+ #include <grpc/support/alloc.h>
42
+ #include <grpc/support/log.h>
43
+ #include <grpc/support/string_util.h>
44
+ #include <grpc/support/useful.h>
45
+
46
+ #include "src/core/channel/channel_stack.h"
47
+ #include "src/core/compression/algorithm_metadata.h"
48
+ #include "src/core/iomgr/timer.h"
49
+ #include "src/core/profiling/timers.h"
50
+ #include "src/core/support/string.h"
51
+ #include "src/core/surface/api_trace.h"
52
+ #include "src/core/surface/call.h"
53
+ #include "src/core/surface/channel.h"
54
+ #include "src/core/surface/completion_queue.h"
55
+ #include "src/core/transport/static_metadata.h"
56
+
57
+ /** The maximum number of concurrent batches possible.
58
+ Based upon the maximum number of individually queueable ops in the batch
59
+ api:
60
+ - initial metadata send
61
+ - message send
62
+ - status/close send (depending on client/server)
63
+ - initial metadata recv
64
+ - message recv
65
+ - status/close recv (depending on client/server) */
66
+ #define MAX_CONCURRENT_BATCHES 6
67
+
68
+ typedef struct {
69
+ grpc_ioreq_completion_func on_complete;
70
+ void *user_data;
71
+ int success;
72
+ } completed_request;
73
+
74
+ #define MAX_SEND_EXTRA_METADATA_COUNT 3
75
+
76
+ /* Status data for a request can come from several sources; this
77
+ enumerates them all, and acts as a priority sorting for which
78
+ status to return to the application - earlier entries override
79
+ later ones */
80
+ typedef enum {
81
+ /* Status came from the application layer overriding whatever
82
+ the wire says */
83
+ STATUS_FROM_API_OVERRIDE = 0,
84
+ /* Status was created by some internal channel stack operation */
85
+ STATUS_FROM_CORE,
86
+ /* Status came from 'the wire' - or somewhere below the surface
87
+ layer */
88
+ STATUS_FROM_WIRE,
89
+ /* Status came from the server sending status */
90
+ STATUS_FROM_SERVER_STATUS,
91
+ STATUS_SOURCE_COUNT
92
+ } status_source;
93
+
94
+ typedef struct {
95
+ gpr_uint8 is_set;
96
+ grpc_status_code code;
97
+ grpc_mdstr *details;
98
+ } received_status;
99
+
100
+ /* How far through the GRPC stream have we read? */
101
+ typedef enum {
102
+ /* We are still waiting for initial metadata to complete */
103
+ READ_STATE_INITIAL = 0,
104
+ /* We have gotten initial metadata, and are reading either
105
+ messages or trailing metadata */
106
+ READ_STATE_GOT_INITIAL_METADATA,
107
+ /* The stream is closed for reading */
108
+ READ_STATE_READ_CLOSED,
109
+ /* The stream is closed for reading & writing */
110
+ READ_STATE_STREAM_CLOSED
111
+ } read_state;
112
+
113
+ typedef enum {
114
+ WRITE_STATE_INITIAL = 0,
115
+ WRITE_STATE_STARTED,
116
+ WRITE_STATE_WRITE_CLOSED
117
+ } write_state;
118
+
119
+ typedef struct batch_control {
120
+ grpc_call *call;
121
+ grpc_cq_completion cq_completion;
122
+ grpc_closure finish_batch;
123
+ void *notify_tag;
124
+ gpr_refcount steps_to_complete;
125
+
126
+ gpr_uint8 send_initial_metadata;
127
+ gpr_uint8 send_message;
128
+ gpr_uint8 send_final_op;
129
+ gpr_uint8 recv_initial_metadata;
130
+ gpr_uint8 recv_message;
131
+ gpr_uint8 recv_final_op;
132
+ gpr_uint8 is_notify_tag_closure;
133
+ gpr_uint8 success;
134
+ } batch_control;
135
+
136
+ struct grpc_call {
137
+ grpc_completion_queue *cq;
138
+ grpc_channel *channel;
139
+ grpc_call *parent;
140
+ grpc_call *first_child;
141
+ /* TODO(ctiller): share with cq if possible? */
142
+ gpr_mu mu;
143
+
144
+ /* client or server call */
145
+ gpr_uint8 is_client;
146
+ /* is the alarm set */
147
+ gpr_uint8 have_alarm;
148
+ /** has grpc_call_destroy been called */
149
+ gpr_uint8 destroy_called;
150
+ /** flag indicating that cancellation is inherited */
151
+ gpr_uint8 cancellation_is_inherited;
152
+ /** bitmask of live batches */
153
+ gpr_uint8 used_batches;
154
+ /** which ops are in-flight */
155
+ gpr_uint8 sent_initial_metadata;
156
+ gpr_uint8 sending_message;
157
+ gpr_uint8 sent_final_op;
158
+ gpr_uint8 received_initial_metadata;
159
+ gpr_uint8 receiving_message;
160
+ gpr_uint8 received_final_op;
161
+
162
+ batch_control active_batches[MAX_CONCURRENT_BATCHES];
163
+
164
+ /* first idx: is_receiving, second idx: is_trailing */
165
+ grpc_metadata_batch metadata_batch[2][2];
166
+
167
+ /* Buffered read metadata waiting to be returned to the application.
168
+ Element 0 is initial metadata, element 1 is trailing metadata. */
169
+ grpc_metadata_array *buffered_metadata[2];
170
+
171
+ /* Received call statuses from various sources */
172
+ received_status status[STATUS_SOURCE_COUNT];
173
+
174
+ /* Compression algorithm for the call */
175
+ grpc_compression_algorithm compression_algorithm;
176
+ /* Supported encodings (compression algorithms), a bitset */
177
+ gpr_uint32 encodings_accepted_by_peer;
178
+
179
+ /* Contexts for various subsystems (security, tracing, ...). */
180
+ grpc_call_context_element context[GRPC_CONTEXT_COUNT];
181
+
182
+ /* Deadline alarm - if have_alarm is non-zero */
183
+ grpc_timer alarm;
184
+
185
+ /* for the client, extra metadata is initial metadata; for the
186
+ server, it's trailing metadata */
187
+ grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT];
188
+ int send_extra_metadata_count;
189
+ gpr_timespec send_deadline;
190
+
191
+ /** siblings: children of the same parent form a list, and this list is
192
+ protected under
193
+ parent->mu */
194
+ grpc_call *sibling_next;
195
+ grpc_call *sibling_prev;
196
+
197
+ grpc_slice_buffer_stream sending_stream;
198
+ grpc_byte_stream *receiving_stream;
199
+ grpc_byte_buffer **receiving_buffer;
200
+ gpr_slice receiving_slice;
201
+ grpc_closure receiving_slice_ready;
202
+ grpc_closure receiving_stream_ready;
203
+ gpr_uint32 test_only_last_message_flags;
204
+
205
+ union {
206
+ struct {
207
+ grpc_status_code *status;
208
+ char **status_details;
209
+ size_t *status_details_capacity;
210
+ } client;
211
+ struct {
212
+ int *cancelled;
213
+ } server;
214
+ } final_op;
215
+ };
216
+
217
+ #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
218
+ #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
219
+ #define CALL_ELEM_FROM_CALL(call, idx) \
220
+ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
221
+ #define CALL_FROM_TOP_ELEM(top_elem) \
222
+ CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem))
223
+
224
+ static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call,
225
+ gpr_timespec deadline);
226
+ static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
227
+ grpc_transport_stream_op *op);
228
+ static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
229
+ grpc_status_code status,
230
+ const char *description);
231
+ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack,
232
+ int success);
233
+ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
234
+ int success);
235
+
236
+ grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
237
+ gpr_uint32 propagation_mask,
238
+ grpc_completion_queue *cq,
239
+ const void *server_transport_data,
240
+ grpc_mdelem **add_initial_metadata,
241
+ size_t add_initial_metadata_count,
242
+ gpr_timespec send_deadline) {
243
+ size_t i, j;
244
+ grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
245
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
246
+ grpc_call *call;
247
+ GPR_TIMER_BEGIN("grpc_call_create", 0);
248
+ call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
249
+ memset(call, 0, sizeof(grpc_call));
250
+ gpr_mu_init(&call->mu);
251
+ call->channel = channel;
252
+ call->cq = cq;
253
+ call->parent = parent_call;
254
+ call->is_client = server_transport_data == NULL;
255
+ if (call->is_client) {
256
+ GPR_ASSERT(add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT);
257
+ for (i = 0; i < add_initial_metadata_count; i++) {
258
+ call->send_extra_metadata[i].md = add_initial_metadata[i];
259
+ }
260
+ call->send_extra_metadata_count = (int)add_initial_metadata_count;
261
+ } else {
262
+ GPR_ASSERT(add_initial_metadata_count == 0);
263
+ call->send_extra_metadata_count = 0;
264
+ }
265
+ for (i = 0; i < 2; i++) {
266
+ for (j = 0; j < 2; j++) {
267
+ call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
268
+ }
269
+ }
270
+ call->send_deadline = send_deadline;
271
+ GRPC_CHANNEL_INTERNAL_REF(channel, "call");
272
+ /* initial refcount dropped by grpc_call_destroy */
273
+ grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call,
274
+ call->context, server_transport_data,
275
+ CALL_STACK_FROM_CALL(call));
276
+ if (cq != NULL) {
277
+ GRPC_CQ_INTERNAL_REF(cq, "bind");
278
+ grpc_call_stack_set_pollset(&exec_ctx, CALL_STACK_FROM_CALL(call),
279
+ grpc_cq_pollset(cq));
280
+ }
281
+ if (parent_call != NULL) {
282
+ GRPC_CALL_INTERNAL_REF(parent_call, "child");
283
+ GPR_ASSERT(call->is_client);
284
+ GPR_ASSERT(!parent_call->is_client);
285
+
286
+ gpr_mu_lock(&parent_call->mu);
287
+
288
+ if (propagation_mask & GRPC_PROPAGATE_DEADLINE) {
289
+ send_deadline = gpr_time_min(
290
+ gpr_convert_clock_type(send_deadline,
291
+ parent_call->send_deadline.clock_type),
292
+ parent_call->send_deadline);
293
+ }
294
+ /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with
295
+ * GRPC_PROPAGATE_STATS_CONTEXT */
296
+ /* TODO(ctiller): This should change to use the appropriate census start_op
297
+ * call. */
298
+ if (propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) {
299
+ GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
300
+ grpc_call_context_set(call, GRPC_CONTEXT_TRACING,
301
+ parent_call->context[GRPC_CONTEXT_TRACING].value,
302
+ NULL);
303
+ } else {
304
+ GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
305
+ }
306
+ if (propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
307
+ call->cancellation_is_inherited = 1;
308
+ }
309
+
310
+ if (parent_call->first_child == NULL) {
311
+ parent_call->first_child = call;
312
+ call->sibling_next = call->sibling_prev = call;
313
+ } else {
314
+ call->sibling_next = parent_call->first_child;
315
+ call->sibling_prev = parent_call->first_child->sibling_prev;
316
+ call->sibling_next->sibling_prev = call->sibling_prev->sibling_next =
317
+ call;
318
+ }
319
+
320
+ gpr_mu_unlock(&parent_call->mu);
321
+ }
322
+ if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) !=
323
+ 0) {
324
+ set_deadline_alarm(&exec_ctx, call, send_deadline);
325
+ }
326
+ grpc_exec_ctx_finish(&exec_ctx);
327
+ GPR_TIMER_END("grpc_call_create", 0);
328
+ return call;
329
+ }
330
+
331
+ void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
332
+ grpc_completion_queue *cq) {
333
+ GPR_ASSERT(cq);
334
+ call->cq = cq;
335
+ GRPC_CQ_INTERNAL_REF(cq, "bind");
336
+ grpc_call_stack_set_pollset(exec_ctx, CALL_STACK_FROM_CALL(call),
337
+ grpc_cq_pollset(cq));
338
+ }
339
+
340
+ #ifdef GRPC_STREAM_REFCOUNT_DEBUG
341
+ #define REF_REASON reason
342
+ #define REF_ARG , const char *reason
343
+ #else
344
+ #define REF_REASON ""
345
+ #define REF_ARG
346
+ #endif
347
+ void grpc_call_internal_ref(grpc_call *c REF_ARG) {
348
+ GRPC_CALL_STACK_REF(CALL_STACK_FROM_CALL(c), REF_REASON);
349
+ }
350
+ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
351
+ GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
352
+ }
353
+
354
+ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, int success) {
355
+ size_t i;
356
+ int ii;
357
+ grpc_call *c = call;
358
+ GPR_TIMER_BEGIN("destroy_call", 0);
359
+ for (i = 0; i < 2; i++) {
360
+ grpc_metadata_batch_destroy(
361
+ &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]);
362
+ }
363
+ if (c->receiving_stream != NULL) {
364
+ grpc_byte_stream_destroy(c->receiving_stream);
365
+ }
366
+ grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c));
367
+ GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->channel, "call");
368
+ gpr_mu_destroy(&c->mu);
369
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
370
+ if (c->status[i].details) {
371
+ GRPC_MDSTR_UNREF(c->status[i].details);
372
+ }
373
+ }
374
+ for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
375
+ GRPC_MDELEM_UNREF(c->send_extra_metadata[ii].md);
376
+ }
377
+ for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
378
+ if (c->context[i].destroy) {
379
+ c->context[i].destroy(c->context[i].value);
380
+ }
381
+ }
382
+ if (c->cq) {
383
+ GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
384
+ }
385
+ gpr_free(c);
386
+ GPR_TIMER_END("destroy_call", 0);
387
+ }
388
+
389
+ static void set_status_code(grpc_call *call, status_source source,
390
+ gpr_uint32 status) {
391
+ if (call->status[source].is_set) return;
392
+
393
+ call->status[source].is_set = 1;
394
+ call->status[source].code = (grpc_status_code)status;
395
+
396
+ /* TODO(ctiller): what to do about the flush that was previously here */
397
+ }
398
+
399
+ static void set_compression_algorithm(grpc_call *call,
400
+ grpc_compression_algorithm algo) {
401
+ call->compression_algorithm = algo;
402
+ }
403
+
404
+ grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
405
+ grpc_call *call) {
406
+ grpc_compression_algorithm algorithm;
407
+ gpr_mu_lock(&call->mu);
408
+ algorithm = call->compression_algorithm;
409
+ gpr_mu_unlock(&call->mu);
410
+ return algorithm;
411
+ }
412
+
413
+ gpr_uint32 grpc_call_test_only_get_message_flags(grpc_call *call) {
414
+ gpr_uint32 flags;
415
+ gpr_mu_lock(&call->mu);
416
+ flags = call->test_only_last_message_flags;
417
+ gpr_mu_unlock(&call->mu);
418
+ return flags;
419
+ }
420
+
421
+ static void destroy_encodings_accepted_by_peer(void *p) { return; }
422
+
423
+ static void set_encodings_accepted_by_peer(grpc_call *call, grpc_mdelem *mdel) {
424
+ size_t i;
425
+ grpc_compression_algorithm algorithm;
426
+ gpr_slice_buffer accept_encoding_parts;
427
+ gpr_slice accept_encoding_slice;
428
+ void *accepted_user_data;
429
+
430
+ accepted_user_data =
431
+ grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
432
+ if (accepted_user_data != NULL) {
433
+ call->encodings_accepted_by_peer =
434
+ (gpr_uint32)(((gpr_uintptr)accepted_user_data) - 1);
435
+ return;
436
+ }
437
+
438
+ accept_encoding_slice = mdel->value->slice;
439
+ gpr_slice_buffer_init(&accept_encoding_parts);
440
+ gpr_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
441
+
442
+ /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
443
+ * zeroes the whole grpc_call */
444
+ /* Always support no compression */
445
+ GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
446
+ for (i = 0; i < accept_encoding_parts.count; i++) {
447
+ const gpr_slice *accept_encoding_entry_slice =
448
+ &accept_encoding_parts.slices[i];
449
+ if (grpc_compression_algorithm_parse(
450
+ (const char *)GPR_SLICE_START_PTR(*accept_encoding_entry_slice),
451
+ GPR_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
452
+ GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
453
+ } else {
454
+ char *accept_encoding_entry_str =
455
+ gpr_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
456
+ gpr_log(GPR_ERROR,
457
+ "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
458
+ accept_encoding_entry_str);
459
+ gpr_free(accept_encoding_entry_str);
460
+ }
461
+ }
462
+
463
+ gpr_slice_buffer_destroy(&accept_encoding_parts);
464
+
465
+ grpc_mdelem_set_user_data(
466
+ mdel, destroy_encodings_accepted_by_peer,
467
+ (void *)(((gpr_uintptr)call->encodings_accepted_by_peer) + 1));
468
+ }
469
+
470
+ gpr_uint32 grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
471
+ gpr_uint32 encodings_accepted_by_peer;
472
+ gpr_mu_lock(&call->mu);
473
+ encodings_accepted_by_peer = call->encodings_accepted_by_peer;
474
+ gpr_mu_unlock(&call->mu);
475
+ return encodings_accepted_by_peer;
476
+ }
477
+
478
+ static void set_status_details(grpc_call *call, status_source source,
479
+ grpc_mdstr *status) {
480
+ if (call->status[source].details != NULL) {
481
+ GRPC_MDSTR_UNREF(call->status[source].details);
482
+ }
483
+ call->status[source].details = status;
484
+ }
485
+
486
+ static void get_final_status(grpc_call *call,
487
+ void (*set_value)(grpc_status_code code,
488
+ void *user_data),
489
+ void *set_value_user_data) {
490
+ int i;
491
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
492
+ if (call->status[i].is_set) {
493
+ set_value(call->status[i].code, set_value_user_data);
494
+ return;
495
+ }
496
+ }
497
+ if (call->is_client) {
498
+ set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
499
+ } else {
500
+ set_value(GRPC_STATUS_OK, set_value_user_data);
501
+ }
502
+ }
503
+
504
+ static void get_final_details(grpc_call *call, char **out_details,
505
+ size_t *out_details_capacity) {
506
+ int i;
507
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
508
+ if (call->status[i].is_set) {
509
+ if (call->status[i].details) {
510
+ gpr_slice details = call->status[i].details->slice;
511
+ size_t len = GPR_SLICE_LENGTH(details);
512
+ if (len + 1 > *out_details_capacity) {
513
+ *out_details_capacity =
514
+ GPR_MAX(len + 1, *out_details_capacity * 3 / 2);
515
+ *out_details = gpr_realloc(*out_details, *out_details_capacity);
516
+ }
517
+ memcpy(*out_details, GPR_SLICE_START_PTR(details), len);
518
+ (*out_details)[len] = 0;
519
+ } else {
520
+ goto no_details;
521
+ }
522
+ return;
523
+ }
524
+ }
525
+
526
+ no_details:
527
+ if (0 == *out_details_capacity) {
528
+ *out_details_capacity = 8;
529
+ *out_details = gpr_malloc(*out_details_capacity);
530
+ }
531
+ **out_details = 0;
532
+ }
533
+
534
+ static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
535
+ return (grpc_linked_mdelem *)&md->internal_data;
536
+ }
537
+
538
+ static int prepare_application_metadata(grpc_call *call, int count,
539
+ grpc_metadata *metadata,
540
+ int is_trailing,
541
+ int prepend_extra_metadata) {
542
+ int i;
543
+ grpc_metadata_batch *batch =
544
+ &call->metadata_batch[0 /* is_receiving */][is_trailing];
545
+ if (prepend_extra_metadata) {
546
+ if (call->send_extra_metadata_count == 0) {
547
+ prepend_extra_metadata = 0;
548
+ } else {
549
+ for (i = 0; i < call->send_extra_metadata_count; i++) {
550
+ GRPC_MDELEM_REF(call->send_extra_metadata[i].md);
551
+ }
552
+ for (i = 1; i < call->send_extra_metadata_count; i++) {
553
+ call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
554
+ }
555
+ for (i = 0; i < call->send_extra_metadata_count - 1; i++) {
556
+ call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1];
557
+ }
558
+ }
559
+ }
560
+ for (i = 0; i < count; i++) {
561
+ grpc_metadata *md = &metadata[i];
562
+ grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
563
+ GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
564
+ l->md = grpc_mdelem_from_string_and_buffer(
565
+ md->key, (const gpr_uint8 *)md->value, md->value_length);
566
+ if (!grpc_header_key_is_legal(grpc_mdstr_as_c_string(l->md->key),
567
+ GRPC_MDSTR_LENGTH(l->md->key))) {
568
+ gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
569
+ grpc_mdstr_as_c_string(l->md->key));
570
+ return 0;
571
+ } else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
572
+ GRPC_MDSTR_LENGTH(l->md->key)) &&
573
+ !grpc_header_nonbin_value_is_legal(
574
+ grpc_mdstr_as_c_string(l->md->value),
575
+ GRPC_MDSTR_LENGTH(l->md->value))) {
576
+ gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
577
+ return 0;
578
+ }
579
+ }
580
+ for (i = 1; i < count; i++) {
581
+ linked_from_md(&metadata[i])->prev = linked_from_md(&metadata[i - 1]);
582
+ }
583
+ for (i = 0; i < count - 1; i++) {
584
+ linked_from_md(&metadata[i])->next = linked_from_md(&metadata[i + 1]);
585
+ }
586
+ switch (prepend_extra_metadata * 2 + (count != 0)) {
587
+ case 0:
588
+ /* no prepend, no metadata => nothing to do */
589
+ batch->list.head = batch->list.tail = NULL;
590
+ break;
591
+ case 1:
592
+ /* metadata, but no prepend */
593
+ batch->list.head = linked_from_md(&metadata[0]);
594
+ batch->list.tail = linked_from_md(&metadata[count - 1]);
595
+ batch->list.head->prev = NULL;
596
+ batch->list.tail->next = NULL;
597
+ break;
598
+ case 2:
599
+ /* prepend, but no md */
600
+ batch->list.head = &call->send_extra_metadata[0];
601
+ batch->list.tail =
602
+ &call->send_extra_metadata[call->send_extra_metadata_count - 1];
603
+ batch->list.head->prev = NULL;
604
+ batch->list.tail->next = NULL;
605
+ break;
606
+ case 3:
607
+ /* prepend AND md */
608
+ batch->list.head = &call->send_extra_metadata[0];
609
+ call->send_extra_metadata[call->send_extra_metadata_count - 1].next =
610
+ linked_from_md(&metadata[0]);
611
+ linked_from_md(&metadata[0])->prev =
612
+ &call->send_extra_metadata[call->send_extra_metadata_count - 1];
613
+ batch->list.tail = linked_from_md(&metadata[count - 1]);
614
+ batch->list.head->prev = NULL;
615
+ batch->list.tail->next = NULL;
616
+ break;
617
+ default:
618
+ GPR_UNREACHABLE_CODE(return 0);
619
+ }
620
+
621
+ return 1;
622
+ }
623
+
624
+ void grpc_call_destroy(grpc_call *c) {
625
+ int cancel;
626
+ grpc_call *parent = c->parent;
627
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
628
+
629
+ GPR_TIMER_BEGIN("grpc_call_destroy", 0);
630
+ GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
631
+
632
+ if (parent) {
633
+ gpr_mu_lock(&parent->mu);
634
+ if (c == parent->first_child) {
635
+ parent->first_child = c->sibling_next;
636
+ if (c == parent->first_child) {
637
+ parent->first_child = NULL;
638
+ }
639
+ c->sibling_prev->sibling_next = c->sibling_next;
640
+ c->sibling_next->sibling_prev = c->sibling_prev;
641
+ }
642
+ gpr_mu_unlock(&parent->mu);
643
+ GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
644
+ }
645
+
646
+ gpr_mu_lock(&c->mu);
647
+ GPR_ASSERT(!c->destroy_called);
648
+ c->destroy_called = 1;
649
+ if (c->have_alarm) {
650
+ grpc_timer_cancel(&exec_ctx, &c->alarm);
651
+ }
652
+ cancel = !c->received_final_op;
653
+ gpr_mu_unlock(&c->mu);
654
+ if (cancel) grpc_call_cancel(c, NULL);
655
+ GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
656
+ grpc_exec_ctx_finish(&exec_ctx);
657
+ GPR_TIMER_END("grpc_call_destroy", 0);
658
+ }
659
+
660
+ grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
661
+ GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
662
+ GPR_ASSERT(!reserved);
663
+ return grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Cancelled",
664
+ NULL);
665
+ }
666
+
667
+ grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
668
+ grpc_status_code status,
669
+ const char *description,
670
+ void *reserved) {
671
+ grpc_call_error r;
672
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
673
+ GRPC_API_TRACE(
674
+ "grpc_call_cancel_with_status("
675
+ "c=%p, status=%d, description=%s, reserved=%p)",
676
+ 4, (c, (int)status, description, reserved));
677
+ GPR_ASSERT(reserved == NULL);
678
+ gpr_mu_lock(&c->mu);
679
+ r = cancel_with_status(&exec_ctx, c, status, description);
680
+ gpr_mu_unlock(&c->mu);
681
+ grpc_exec_ctx_finish(&exec_ctx);
682
+ return r;
683
+ }
684
+
685
+ typedef struct cancel_closure {
686
+ grpc_closure closure;
687
+ grpc_call *call;
688
+ grpc_status_code status;
689
+ } cancel_closure;
690
+
691
+ static void done_cancel(grpc_exec_ctx *exec_ctx, void *ccp, int success) {
692
+ cancel_closure *cc = ccp;
693
+ GRPC_CALL_INTERNAL_UNREF(exec_ctx, cc->call, "cancel");
694
+ gpr_free(cc);
695
+ }
696
+
697
+ static void send_cancel(grpc_exec_ctx *exec_ctx, void *ccp, int success) {
698
+ grpc_transport_stream_op op;
699
+ cancel_closure *cc = ccp;
700
+ memset(&op, 0, sizeof(op));
701
+ op.cancel_with_status = cc->status;
702
+ /* reuse closure to catch completion */
703
+ grpc_closure_init(&cc->closure, done_cancel, cc);
704
+ op.on_complete = &cc->closure;
705
+ execute_op(exec_ctx, cc->call, &op);
706
+ }
707
+
708
+ static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
709
+ grpc_status_code status,
710
+ const char *description) {
711
+ grpc_mdstr *details =
712
+ description ? grpc_mdstr_from_string(description) : NULL;
713
+ cancel_closure *cc = gpr_malloc(sizeof(*cc));
714
+
715
+ GPR_ASSERT(status != GRPC_STATUS_OK);
716
+
717
+ set_status_code(c, STATUS_FROM_API_OVERRIDE, (gpr_uint32)status);
718
+ set_status_details(c, STATUS_FROM_API_OVERRIDE, details);
719
+
720
+ grpc_closure_init(&cc->closure, send_cancel, cc);
721
+ cc->call = c;
722
+ cc->status = status;
723
+ GRPC_CALL_INTERNAL_REF(c, "cancel");
724
+ grpc_exec_ctx_enqueue(exec_ctx, &cc->closure, 1);
725
+
726
+ return GRPC_CALL_OK;
727
+ }
728
+
729
+ static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
730
+ grpc_transport_stream_op *op) {
731
+ grpc_call_element *elem;
732
+
733
+ GPR_TIMER_BEGIN("execute_op", 0);
734
+ elem = CALL_ELEM_FROM_CALL(call, 0);
735
+ op->context = call->context;
736
+ elem->filter->start_transport_stream_op(exec_ctx, elem, op);
737
+ GPR_TIMER_END("execute_op", 0);
738
+ }
739
+
740
+ char *grpc_call_get_peer(grpc_call *call) {
741
+ grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
742
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
743
+ char *result;
744
+ GRPC_API_TRACE("grpc_call_get_peer(%p)", 1, (call));
745
+ result = elem->filter->get_peer(&exec_ctx, elem);
746
+ if (result == NULL) {
747
+ result = grpc_channel_get_target(call->channel);
748
+ }
749
+ if (result == NULL) {
750
+ result = gpr_strdup("unknown");
751
+ }
752
+ grpc_exec_ctx_finish(&exec_ctx);
753
+ return result;
754
+ }
755
+
756
+ grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
757
+ return CALL_FROM_TOP_ELEM(elem);
758
+ }
759
+
760
+ static void call_alarm(grpc_exec_ctx *exec_ctx, void *arg, int success) {
761
+ grpc_call *call = arg;
762
+ gpr_mu_lock(&call->mu);
763
+ call->have_alarm = 0;
764
+ if (success) {
765
+ cancel_with_status(exec_ctx, call, GRPC_STATUS_DEADLINE_EXCEEDED,
766
+ "Deadline Exceeded");
767
+ }
768
+ gpr_mu_unlock(&call->mu);
769
+ GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "alarm");
770
+ }
771
+
772
+ static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call,
773
+ gpr_timespec deadline) {
774
+ if (call->have_alarm) {
775
+ gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice");
776
+ assert(0);
777
+ return;
778
+ }
779
+ GRPC_CALL_INTERNAL_REF(call, "alarm");
780
+ call->have_alarm = 1;
781
+ call->send_deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
782
+ grpc_timer_init(exec_ctx, &call->alarm, call->send_deadline, call_alarm, call,
783
+ gpr_now(GPR_CLOCK_MONOTONIC));
784
+ }
785
+
786
+ /* we offset status by a small amount when storing it into transport metadata
787
+ as metadata cannot store a 0 value (which is used as OK for grpc_status_codes
788
+ */
789
+ #define STATUS_OFFSET 1
790
+ static void destroy_status(void *ignored) {}
791
+
792
+ static gpr_uint32 decode_status(grpc_mdelem *md) {
793
+ gpr_uint32 status;
794
+ void *user_data;
795
+ if (md == GRPC_MDELEM_GRPC_STATUS_0) return 0;
796
+ if (md == GRPC_MDELEM_GRPC_STATUS_1) return 1;
797
+ if (md == GRPC_MDELEM_GRPC_STATUS_2) return 2;
798
+ user_data = grpc_mdelem_get_user_data(md, destroy_status);
799
+ if (user_data != NULL) {
800
+ status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET;
801
+ } else {
802
+ if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
803
+ GPR_SLICE_LENGTH(md->value->slice),
804
+ &status)) {
805
+ status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
806
+ }
807
+ grpc_mdelem_set_user_data(md, destroy_status,
808
+ (void *)(gpr_intptr)(status + STATUS_OFFSET));
809
+ }
810
+ return status;
811
+ }
812
+
813
+ static gpr_uint32 decode_compression(grpc_mdelem *md) {
814
+ grpc_compression_algorithm algorithm =
815
+ grpc_compression_algorithm_from_mdstr(md->value);
816
+ if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
817
+ const char *md_c_str = grpc_mdstr_as_c_string(md->value);
818
+ gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str);
819
+ }
820
+ return algorithm;
821
+ }
822
+
823
+ static grpc_mdelem *recv_common_filter(grpc_call *call, grpc_mdelem *elem) {
824
+ if (elem->key == GRPC_MDSTR_GRPC_STATUS) {
825
+ GPR_TIMER_BEGIN("status", 0);
826
+ set_status_code(call, STATUS_FROM_WIRE, decode_status(elem));
827
+ GPR_TIMER_END("status", 0);
828
+ return NULL;
829
+ } else if (elem->key == GRPC_MDSTR_GRPC_MESSAGE) {
830
+ GPR_TIMER_BEGIN("status-details", 0);
831
+ set_status_details(call, STATUS_FROM_WIRE, GRPC_MDSTR_REF(elem->value));
832
+ GPR_TIMER_END("status-details", 0);
833
+ return NULL;
834
+ }
835
+ return elem;
836
+ }
837
+
838
+ static grpc_mdelem *publish_app_metadata(grpc_call *call, grpc_mdelem *elem,
839
+ int is_trailing) {
840
+ grpc_metadata_array *dest;
841
+ grpc_metadata *mdusr;
842
+ GPR_TIMER_BEGIN("publish_app_metadata", 0);
843
+ dest = call->buffered_metadata[is_trailing];
844
+ if (dest->count == dest->capacity) {
845
+ dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2);
846
+ dest->metadata =
847
+ gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
848
+ }
849
+ mdusr = &dest->metadata[dest->count++];
850
+ mdusr->key = grpc_mdstr_as_c_string(elem->key);
851
+ mdusr->value = grpc_mdstr_as_c_string(elem->value);
852
+ mdusr->value_length = GPR_SLICE_LENGTH(elem->value->slice);
853
+ GPR_TIMER_END("publish_app_metadata", 0);
854
+ return elem;
855
+ }
856
+
857
+ static grpc_mdelem *recv_initial_filter(void *callp, grpc_mdelem *elem) {
858
+ grpc_call *call = callp;
859
+ elem = recv_common_filter(call, elem);
860
+ if (elem == NULL) {
861
+ return NULL;
862
+ } else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) {
863
+ GPR_TIMER_BEGIN("compression_algorithm", 0);
864
+ set_compression_algorithm(call, decode_compression(elem));
865
+ GPR_TIMER_END("compression_algorithm", 0);
866
+ return NULL;
867
+ } else if (elem->key == GRPC_MDSTR_GRPC_ACCEPT_ENCODING) {
868
+ GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
869
+ set_encodings_accepted_by_peer(call, elem);
870
+ GPR_TIMER_END("encodings_accepted_by_peer", 0);
871
+ return NULL;
872
+ } else {
873
+ return publish_app_metadata(call, elem, 0);
874
+ }
875
+ }
876
+
877
+ static grpc_mdelem *recv_trailing_filter(void *callp, grpc_mdelem *elem) {
878
+ grpc_call *call = callp;
879
+ elem = recv_common_filter(call, elem);
880
+ if (elem == NULL) {
881
+ return NULL;
882
+ } else {
883
+ return publish_app_metadata(call, elem, 1);
884
+ }
885
+ }
886
+
887
+ grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
888
+ return CALL_STACK_FROM_CALL(call);
889
+ }
890
+
891
+ /*
892
+ * BATCH API IMPLEMENTATION
893
+ */
894
+
895
+ static void set_status_value_directly(grpc_status_code status, void *dest) {
896
+ *(grpc_status_code *)dest = status;
897
+ }
898
+
899
+ static void set_cancelled_value(grpc_status_code status, void *dest) {
900
+ *(int *)dest = (status != GRPC_STATUS_OK);
901
+ }
902
+
903
+ static int are_write_flags_valid(gpr_uint32 flags) {
904
+ /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
905
+ const gpr_uint32 allowed_write_positions =
906
+ (GRPC_WRITE_USED_MASK | GRPC_WRITE_INTERNAL_USED_MASK);
907
+ const gpr_uint32 invalid_positions = ~allowed_write_positions;
908
+ return !(flags & invalid_positions);
909
+ }
910
+
911
+ static batch_control *allocate_batch_control(grpc_call *call) {
912
+ size_t i;
913
+ for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
914
+ if ((call->used_batches & (1 << i)) == 0) {
915
+ call->used_batches =
916
+ (gpr_uint8)(call->used_batches | (gpr_uint8)(1 << i));
917
+ return &call->active_batches[i];
918
+ }
919
+ }
920
+ return NULL;
921
+ }
922
+
923
+ static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
924
+ grpc_cq_completion *storage) {
925
+ batch_control *bctl = user_data;
926
+ grpc_call *call = bctl->call;
927
+ gpr_mu_lock(&call->mu);
928
+ call->used_batches = (gpr_uint8)(
929
+ call->used_batches & ~(gpr_uint8)(1 << (bctl - call->active_batches)));
930
+ gpr_mu_unlock(&call->mu);
931
+ GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
932
+ }
933
+
934
+ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
935
+ batch_control *bctl) {
936
+ grpc_call *call = bctl->call;
937
+ if (bctl->is_notify_tag_closure) {
938
+ grpc_exec_ctx_enqueue(exec_ctx, bctl->notify_tag, bctl->success);
939
+ gpr_mu_lock(&call->mu);
940
+ bctl->call->used_batches =
941
+ (gpr_uint8)(bctl->call->used_batches &
942
+ ~(gpr_uint8)(1 << (bctl - bctl->call->active_batches)));
943
+ gpr_mu_unlock(&call->mu);
944
+ GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
945
+ } else {
946
+ grpc_cq_end_op(exec_ctx, bctl->call->cq, bctl->notify_tag, bctl->success,
947
+ finish_batch_completion, bctl, &bctl->cq_completion);
948
+ }
949
+ }
950
+
951
+ static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
952
+ batch_control *bctl) {
953
+ grpc_call *call = bctl->call;
954
+ for (;;) {
955
+ size_t remaining = call->receiving_stream->length -
956
+ (*call->receiving_buffer)->data.raw.slice_buffer.length;
957
+ if (remaining == 0) {
958
+ call->receiving_message = 0;
959
+ grpc_byte_stream_destroy(call->receiving_stream);
960
+ call->receiving_stream = NULL;
961
+ if (gpr_unref(&bctl->steps_to_complete)) {
962
+ post_batch_completion(exec_ctx, bctl);
963
+ }
964
+ return;
965
+ }
966
+ if (grpc_byte_stream_next(exec_ctx, call->receiving_stream,
967
+ &call->receiving_slice, remaining,
968
+ &call->receiving_slice_ready)) {
969
+ gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
970
+ call->receiving_slice);
971
+ } else {
972
+ return;
973
+ }
974
+ }
975
+ }
976
+
977
+ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
978
+ int success) {
979
+ batch_control *bctl = bctlp;
980
+ grpc_call *call = bctl->call;
981
+
982
+ GPR_ASSERT(success);
983
+ gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
984
+ call->receiving_slice);
985
+
986
+ continue_receiving_slices(exec_ctx, bctl);
987
+ }
988
+
989
+ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, int success) {
990
+ batch_control *bctl = bctlp;
991
+ grpc_call *call = bctl->call;
992
+ grpc_call *child_call;
993
+ grpc_call *next_child_call;
994
+
995
+ gpr_mu_lock(&call->mu);
996
+ if (bctl->send_initial_metadata) {
997
+ grpc_metadata_batch_destroy(
998
+ &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
999
+ }
1000
+ if (bctl->send_message) {
1001
+ call->sending_message = 0;
1002
+ }
1003
+ if (bctl->send_final_op) {
1004
+ grpc_metadata_batch_destroy(
1005
+ &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
1006
+ }
1007
+ if (bctl->recv_initial_metadata) {
1008
+ grpc_metadata_batch *md =
1009
+ &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
1010
+ grpc_metadata_batch_filter(md, recv_initial_filter, call);
1011
+
1012
+ if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
1013
+ 0 &&
1014
+ !call->is_client) {
1015
+ GPR_TIMER_BEGIN("set_deadline_alarm", 0);
1016
+ set_deadline_alarm(exec_ctx, call, md->deadline);
1017
+ GPR_TIMER_END("set_deadline_alarm", 0);
1018
+ }
1019
+ }
1020
+ if (bctl->recv_final_op) {
1021
+ grpc_metadata_batch *md =
1022
+ &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
1023
+ grpc_metadata_batch_filter(md, recv_trailing_filter, call);
1024
+
1025
+ if (call->have_alarm) {
1026
+ grpc_timer_cancel(exec_ctx, &call->alarm);
1027
+ }
1028
+ /* propagate cancellation to any interested children */
1029
+ child_call = call->first_child;
1030
+ if (child_call != NULL) {
1031
+ do {
1032
+ next_child_call = child_call->sibling_next;
1033
+ if (child_call->cancellation_is_inherited) {
1034
+ GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
1035
+ grpc_call_cancel(child_call, NULL);
1036
+ GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
1037
+ }
1038
+ child_call = next_child_call;
1039
+ } while (child_call != call->first_child);
1040
+ }
1041
+
1042
+ if (call->is_client) {
1043
+ get_final_status(call, set_status_value_directly,
1044
+ call->final_op.client.status);
1045
+ get_final_details(call, call->final_op.client.status_details,
1046
+ call->final_op.client.status_details_capacity);
1047
+ } else {
1048
+ get_final_status(call, set_cancelled_value,
1049
+ call->final_op.server.cancelled);
1050
+ }
1051
+
1052
+ success = 1;
1053
+ }
1054
+ bctl->success = success != 0;
1055
+ gpr_mu_unlock(&call->mu);
1056
+ if (gpr_unref(&bctl->steps_to_complete)) {
1057
+ post_batch_completion(exec_ctx, bctl);
1058
+ }
1059
+ }
1060
+
1061
+ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
1062
+ int success) {
1063
+ batch_control *bctl = bctlp;
1064
+ grpc_call *call = bctl->call;
1065
+
1066
+ if (call->receiving_stream == NULL) {
1067
+ *call->receiving_buffer = NULL;
1068
+ if (gpr_unref(&bctl->steps_to_complete)) {
1069
+ post_batch_completion(exec_ctx, bctl);
1070
+ }
1071
+ } else if (call->receiving_stream->length >
1072
+ grpc_channel_get_max_message_length(call->channel)) {
1073
+ cancel_with_status(exec_ctx, call, GRPC_STATUS_INTERNAL,
1074
+ "Max message size exceeded");
1075
+ grpc_byte_stream_destroy(call->receiving_stream);
1076
+ call->receiving_stream = NULL;
1077
+ *call->receiving_buffer = NULL;
1078
+ if (gpr_unref(&bctl->steps_to_complete)) {
1079
+ post_batch_completion(exec_ctx, bctl);
1080
+ }
1081
+ } else {
1082
+ call->test_only_last_message_flags = call->receiving_stream->flags;
1083
+ if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&
1084
+ (call->compression_algorithm > GRPC_COMPRESS_NONE)) {
1085
+ *call->receiving_buffer = grpc_raw_compressed_byte_buffer_create(
1086
+ NULL, 0, call->compression_algorithm);
1087
+ } else {
1088
+ *call->receiving_buffer = grpc_raw_byte_buffer_create(NULL, 0);
1089
+ }
1090
+ grpc_closure_init(&call->receiving_slice_ready, receiving_slice_ready,
1091
+ bctl);
1092
+ continue_receiving_slices(exec_ctx, bctl);
1093
+ /* early out */
1094
+ return;
1095
+ }
1096
+ }
1097
+
1098
+ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1099
+ grpc_call *call, const grpc_op *ops,
1100
+ size_t nops, void *notify_tag,
1101
+ int is_notify_tag_closure) {
1102
+ grpc_transport_stream_op stream_op;
1103
+ size_t i;
1104
+ const grpc_op *op;
1105
+ batch_control *bctl;
1106
+ int num_completion_callbacks_needed = 1;
1107
+ grpc_call_error error = GRPC_CALL_OK;
1108
+
1109
+ GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
1110
+
1111
+ GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
1112
+
1113
+ memset(&stream_op, 0, sizeof(stream_op));
1114
+
1115
+ /* TODO(ctiller): this feels like it could be made lock-free */
1116
+ gpr_mu_lock(&call->mu);
1117
+ bctl = allocate_batch_control(call);
1118
+ memset(bctl, 0, sizeof(*bctl));
1119
+ bctl->call = call;
1120
+ bctl->notify_tag = notify_tag;
1121
+ bctl->is_notify_tag_closure = (gpr_uint8)(is_notify_tag_closure != 0);
1122
+
1123
+ if (nops == 0) {
1124
+ GRPC_CALL_INTERNAL_REF(call, "completion");
1125
+ bctl->success = 1;
1126
+ if (!is_notify_tag_closure) {
1127
+ grpc_cq_begin_op(call->cq, notify_tag);
1128
+ }
1129
+ gpr_mu_unlock(&call->mu);
1130
+ post_batch_completion(exec_ctx, bctl);
1131
+ error = GRPC_CALL_OK;
1132
+ goto done;
1133
+ }
1134
+
1135
+ /* rewrite batch ops into a transport op */
1136
+ for (i = 0; i < nops; i++) {
1137
+ op = &ops[i];
1138
+ if (op->reserved != NULL) {
1139
+ error = GRPC_CALL_ERROR;
1140
+ goto done_with_error;
1141
+ }
1142
+ switch (op->op) {
1143
+ case GRPC_OP_SEND_INITIAL_METADATA:
1144
+ /* Flag validation: currently allow no flags */
1145
+ if (op->flags != 0) {
1146
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1147
+ goto done_with_error;
1148
+ }
1149
+ if (call->sent_initial_metadata) {
1150
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1151
+ goto done_with_error;
1152
+ }
1153
+ if (op->data.send_initial_metadata.count > INT_MAX) {
1154
+ error = GRPC_CALL_ERROR_INVALID_METADATA;
1155
+ goto done_with_error;
1156
+ }
1157
+ bctl->send_initial_metadata = 1;
1158
+ call->sent_initial_metadata = 1;
1159
+ if (!prepare_application_metadata(
1160
+ call, (int)op->data.send_initial_metadata.count,
1161
+ op->data.send_initial_metadata.metadata, 0, call->is_client)) {
1162
+ error = GRPC_CALL_ERROR_INVALID_METADATA;
1163
+ goto done_with_error;
1164
+ }
1165
+ /* TODO(ctiller): just make these the same variable? */
1166
+ call->metadata_batch[0][0].deadline = call->send_deadline;
1167
+ stream_op.send_initial_metadata =
1168
+ &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
1169
+ break;
1170
+ case GRPC_OP_SEND_MESSAGE:
1171
+ if (!are_write_flags_valid(op->flags)) {
1172
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1173
+ goto done_with_error;
1174
+ }
1175
+ if (op->data.send_message == NULL) {
1176
+ error = GRPC_CALL_ERROR_INVALID_MESSAGE;
1177
+ goto done_with_error;
1178
+ }
1179
+ if (call->sending_message) {
1180
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1181
+ goto done_with_error;
1182
+ }
1183
+ bctl->send_message = 1;
1184
+ call->sending_message = 1;
1185
+ grpc_slice_buffer_stream_init(
1186
+ &call->sending_stream,
1187
+ &op->data.send_message->data.raw.slice_buffer, op->flags);
1188
+ stream_op.send_message = &call->sending_stream.base;
1189
+ break;
1190
+ case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
1191
+ /* Flag validation: currently allow no flags */
1192
+ if (op->flags != 0) {
1193
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1194
+ goto done_with_error;
1195
+ }
1196
+ if (!call->is_client) {
1197
+ error = GRPC_CALL_ERROR_NOT_ON_SERVER;
1198
+ goto done_with_error;
1199
+ }
1200
+ if (call->sent_final_op) {
1201
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1202
+ goto done_with_error;
1203
+ }
1204
+ bctl->send_final_op = 1;
1205
+ call->sent_final_op = 1;
1206
+ stream_op.send_trailing_metadata =
1207
+ &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
1208
+ break;
1209
+ case GRPC_OP_SEND_STATUS_FROM_SERVER:
1210
+ /* Flag validation: currently allow no flags */
1211
+ if (op->flags != 0) {
1212
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1213
+ goto done_with_error;
1214
+ }
1215
+ if (call->is_client) {
1216
+ error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
1217
+ goto done_with_error;
1218
+ }
1219
+ if (call->sent_final_op) {
1220
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1221
+ goto done_with_error;
1222
+ }
1223
+ if (op->data.send_status_from_server.trailing_metadata_count >
1224
+ INT_MAX) {
1225
+ error = GRPC_CALL_ERROR_INVALID_METADATA;
1226
+ goto done_with_error;
1227
+ }
1228
+ bctl->send_final_op = 1;
1229
+ call->sent_final_op = 1;
1230
+ call->send_extra_metadata_count = 1;
1231
+ call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
1232
+ call->channel, op->data.send_status_from_server.status);
1233
+ if (op->data.send_status_from_server.status_details != NULL) {
1234
+ call->send_extra_metadata[1].md = grpc_mdelem_from_metadata_strings(
1235
+ GRPC_MDSTR_GRPC_MESSAGE,
1236
+ grpc_mdstr_from_string(
1237
+ op->data.send_status_from_server.status_details));
1238
+ call->send_extra_metadata_count++;
1239
+ set_status_details(
1240
+ call, STATUS_FROM_API_OVERRIDE,
1241
+ GRPC_MDSTR_REF(call->send_extra_metadata[1].md->value));
1242
+ }
1243
+ set_status_code(call, STATUS_FROM_API_OVERRIDE,
1244
+ (gpr_uint32)op->data.send_status_from_server.status);
1245
+ if (!prepare_application_metadata(
1246
+ call,
1247
+ (int)op->data.send_status_from_server.trailing_metadata_count,
1248
+ op->data.send_status_from_server.trailing_metadata, 1, 1)) {
1249
+ error = GRPC_CALL_ERROR_INVALID_METADATA;
1250
+ goto done_with_error;
1251
+ }
1252
+ stream_op.send_trailing_metadata =
1253
+ &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
1254
+ break;
1255
+ case GRPC_OP_RECV_INITIAL_METADATA:
1256
+ /* Flag validation: currently allow no flags */
1257
+ if (op->flags != 0) {
1258
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1259
+ goto done_with_error;
1260
+ }
1261
+ if (call->received_initial_metadata) {
1262
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1263
+ goto done_with_error;
1264
+ }
1265
+ call->received_initial_metadata = 1;
1266
+ call->buffered_metadata[0] = op->data.recv_initial_metadata;
1267
+ bctl->recv_initial_metadata = 1;
1268
+ stream_op.recv_initial_metadata =
1269
+ &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
1270
+ break;
1271
+ case GRPC_OP_RECV_MESSAGE:
1272
+ /* Flag validation: currently allow no flags */
1273
+ if (op->flags != 0) {
1274
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1275
+ goto done_with_error;
1276
+ }
1277
+ if (call->receiving_message) {
1278
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1279
+ goto done_with_error;
1280
+ }
1281
+ call->receiving_message = 1;
1282
+ bctl->recv_message = 1;
1283
+ call->receiving_buffer = op->data.recv_message;
1284
+ stream_op.recv_message = &call->receiving_stream;
1285
+ grpc_closure_init(&call->receiving_stream_ready, receiving_stream_ready,
1286
+ bctl);
1287
+ stream_op.recv_message_ready = &call->receiving_stream_ready;
1288
+ num_completion_callbacks_needed++;
1289
+ break;
1290
+ case GRPC_OP_RECV_STATUS_ON_CLIENT:
1291
+ /* Flag validation: currently allow no flags */
1292
+ if (op->flags != 0) {
1293
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1294
+ goto done_with_error;
1295
+ }
1296
+ if (!call->is_client) {
1297
+ error = GRPC_CALL_ERROR_NOT_ON_SERVER;
1298
+ goto done_with_error;
1299
+ }
1300
+ if (call->received_final_op) {
1301
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1302
+ goto done_with_error;
1303
+ }
1304
+ call->received_final_op = 1;
1305
+ call->buffered_metadata[1] =
1306
+ op->data.recv_status_on_client.trailing_metadata;
1307
+ call->final_op.client.status = op->data.recv_status_on_client.status;
1308
+ call->final_op.client.status_details =
1309
+ op->data.recv_status_on_client.status_details;
1310
+ call->final_op.client.status_details_capacity =
1311
+ op->data.recv_status_on_client.status_details_capacity;
1312
+ bctl->recv_final_op = 1;
1313
+ stream_op.recv_trailing_metadata =
1314
+ &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
1315
+ break;
1316
+ case GRPC_OP_RECV_CLOSE_ON_SERVER:
1317
+ /* Flag validation: currently allow no flags */
1318
+ if (op->flags != 0) {
1319
+ error = GRPC_CALL_ERROR_INVALID_FLAGS;
1320
+ goto done_with_error;
1321
+ }
1322
+ if (call->is_client) {
1323
+ error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
1324
+ goto done_with_error;
1325
+ }
1326
+ if (call->received_final_op) {
1327
+ error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1328
+ goto done_with_error;
1329
+ }
1330
+ call->received_final_op = 1;
1331
+ call->final_op.server.cancelled =
1332
+ op->data.recv_close_on_server.cancelled;
1333
+ bctl->recv_final_op = 1;
1334
+ stream_op.recv_trailing_metadata =
1335
+ &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
1336
+ break;
1337
+ }
1338
+ }
1339
+
1340
+ GRPC_CALL_INTERNAL_REF(call, "completion");
1341
+ if (!is_notify_tag_closure) {
1342
+ grpc_cq_begin_op(call->cq, notify_tag);
1343
+ }
1344
+ gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
1345
+
1346
+ stream_op.context = call->context;
1347
+ grpc_closure_init(&bctl->finish_batch, finish_batch, bctl);
1348
+ stream_op.on_complete = &bctl->finish_batch;
1349
+ gpr_mu_unlock(&call->mu);
1350
+
1351
+ execute_op(exec_ctx, call, &stream_op);
1352
+
1353
+ done:
1354
+ GPR_TIMER_END("grpc_call_start_batch", 0);
1355
+ return error;
1356
+
1357
+ done_with_error:
1358
+ /* reverse any mutations that occured */
1359
+ if (bctl->send_initial_metadata) {
1360
+ call->sent_initial_metadata = 0;
1361
+ grpc_metadata_batch_clear(&call->metadata_batch[0][0]);
1362
+ }
1363
+ if (bctl->send_message) {
1364
+ call->sending_message = 0;
1365
+ grpc_byte_stream_destroy(&call->sending_stream.base);
1366
+ }
1367
+ if (bctl->send_final_op) {
1368
+ call->sent_final_op = 0;
1369
+ grpc_metadata_batch_clear(&call->metadata_batch[0][1]);
1370
+ }
1371
+ if (bctl->recv_initial_metadata) {
1372
+ call->received_initial_metadata = 0;
1373
+ }
1374
+ if (bctl->recv_message) {
1375
+ call->receiving_message = 0;
1376
+ }
1377
+ if (bctl->recv_final_op) {
1378
+ call->received_final_op = 0;
1379
+ }
1380
+ gpr_mu_unlock(&call->mu);
1381
+ goto done;
1382
+ }
1383
+
1384
+ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
1385
+ size_t nops, void *tag, void *reserved) {
1386
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
1387
+ grpc_call_error err;
1388
+
1389
+ GRPC_API_TRACE(
1390
+ "grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, reserved=%p)",
1391
+ 5, (call, ops, (unsigned long)nops, tag, reserved));
1392
+
1393
+ if (reserved != NULL) {
1394
+ err = GRPC_CALL_ERROR;
1395
+ } else {
1396
+ err = call_start_batch(&exec_ctx, call, ops, nops, tag, 0);
1397
+ }
1398
+
1399
+ grpc_exec_ctx_finish(&exec_ctx);
1400
+ return err;
1401
+ }
1402
+
1403
+ grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx,
1404
+ grpc_call *call,
1405
+ const grpc_op *ops,
1406
+ size_t nops,
1407
+ grpc_closure *closure) {
1408
+ return call_start_batch(exec_ctx, call, ops, nops, closure, 1);
1409
+ }
1410
+
1411
+ void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
1412
+ void *value, void (*destroy)(void *value)) {
1413
+ if (call->context[elem].destroy) {
1414
+ call->context[elem].destroy(call->context[elem].value);
1415
+ }
1416
+ call->context[elem].value = value;
1417
+ call->context[elem].destroy = destroy;
1418
+ }
1419
+
1420
+ void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) {
1421
+ return call->context[elem].value;
1422
+ }
1423
+
1424
+ gpr_uint8 grpc_call_is_client(grpc_call *call) { return call->is_client; }