grpc 0.14.1 → 0.15.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 (277) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +1398 -817
  3. data/include/grpc/compression.h +2 -1
  4. data/include/grpc/grpc.h +10 -1
  5. data/include/grpc/grpc_cronet.h +51 -0
  6. data/include/grpc/grpc_posix.h +70 -0
  7. data/include/grpc/impl/codegen/atm.h +2 -2
  8. data/include/grpc/impl/codegen/{atm_win32.h → atm_windows.h} +3 -3
  9. data/include/grpc/impl/codegen/compression_types.h +39 -5
  10. data/include/grpc/impl/codegen/connectivity_state.h +1 -1
  11. data/include/grpc/impl/codegen/grpc_types.h +10 -0
  12. data/include/grpc/impl/codegen/log.h +2 -1
  13. data/include/grpc/impl/codegen/port_platform.h +30 -12
  14. data/include/grpc/impl/codegen/slice_buffer.h +2 -3
  15. data/include/grpc/impl/codegen/sync.h +2 -2
  16. data/include/grpc/impl/codegen/{sync_win32.h → sync_windows.h} +3 -3
  17. data/include/grpc/support/{sync_win32.h → atm_windows.h} +4 -4
  18. data/include/grpc/support/avl.h +5 -0
  19. data/include/grpc/support/{log_win32.h → log_windows.h} +3 -3
  20. data/include/grpc/support/string_util.h +2 -1
  21. data/include/grpc/support/{atm_win32.h → sync_windows.h} +4 -4
  22. data/src/core/ext/census/gen/census.pb.c +179 -0
  23. data/src/core/ext/census/gen/census.pb.h +294 -0
  24. data/src/core/ext/census/grpc_filter.c +11 -7
  25. data/src/core/ext/client_config/channel_connectivity.c +28 -14
  26. data/src/core/ext/client_config/client_channel.c +77 -53
  27. data/src/core/ext/client_config/connector.h +1 -1
  28. data/src/core/ext/client_config/lb_policy.c +9 -6
  29. data/src/core/ext/client_config/lb_policy.h +9 -5
  30. data/src/core/ext/client_config/subchannel.c +58 -39
  31. data/src/core/ext/client_config/subchannel.h +3 -2
  32. data/src/core/ext/client_config/subchannel_call_holder.c +34 -19
  33. data/src/core/ext/client_config/subchannel_call_holder.h +2 -1
  34. data/src/core/ext/client_config/subchannel_index.c +20 -9
  35. data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +7 -7
  36. data/src/core/ext/lb_policy/grpclb/load_balancer_api.h +5 -5
  37. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/{v0 → v1}/load_balancer.pb.c +29 -30
  38. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +178 -0
  39. data/src/core/ext/lb_policy/pick_first/pick_first.c +65 -45
  40. data/src/core/ext/lb_policy/round_robin/round_robin.c +84 -43
  41. data/src/core/ext/load_reporting/load_reporting.c +133 -0
  42. data/src/core/ext/load_reporting/load_reporting.h +75 -0
  43. data/src/core/ext/load_reporting/load_reporting_filter.c +151 -0
  44. data/src/core/ext/load_reporting/load_reporting_filter.h +41 -0
  45. data/src/core/ext/resolver/dns/native/dns_resolver.c +22 -8
  46. data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +2 -2
  47. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +4 -4
  48. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c +95 -0
  49. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +14 -18
  50. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +49 -24
  51. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c +82 -0
  52. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +104 -60
  53. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +232 -0
  54. data/src/{ruby/ext/grpc/rb_signal.c → core/ext/transport/chttp2/transport/bin_decoder.h} +27 -31
  55. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +481 -260
  56. data/src/core/ext/transport/chttp2/transport/frame.h +1 -7
  57. data/src/core/ext/transport/chttp2/transport/frame_data.c +44 -27
  58. data/src/core/ext/transport/chttp2/transport/frame_data.h +6 -5
  59. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +23 -17
  60. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +2 -2
  61. data/src/core/ext/transport/chttp2/transport/frame_ping.c +12 -7
  62. data/src/core/ext/transport/chttp2/transport/frame_ping.h +3 -3
  63. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +25 -12
  64. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +2 -2
  65. data/src/core/ext/transport/chttp2/transport/frame_settings.c +23 -21
  66. data/src/core/ext/transport/chttp2/transport/frame_settings.h +2 -2
  67. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +17 -9
  68. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +2 -2
  69. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +365 -287
  70. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +8 -6
  71. data/src/core/ext/transport/chttp2/transport/hpack_table.c +24 -20
  72. data/src/core/ext/transport/chttp2/transport/hpack_table.h +5 -4
  73. data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +1 -0
  74. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +1 -0
  75. data/src/core/ext/transport/chttp2/transport/internal.h +34 -32
  76. data/src/core/ext/transport/chttp2/transport/parsing.c +296 -212
  77. data/src/core/ext/transport/chttp2/transport/writing.c +12 -9
  78. data/src/core/lib/channel/channel_args.c +26 -12
  79. data/src/core/lib/channel/channel_args.h +1 -1
  80. data/src/core/lib/channel/channel_stack.c +12 -8
  81. data/src/core/lib/channel/channel_stack.h +27 -11
  82. data/src/core/lib/channel/channel_stack_builder.c +2 -2
  83. data/src/core/lib/channel/compress_filter.c +26 -31
  84. data/src/core/lib/channel/compress_filter.h +4 -4
  85. data/src/core/lib/channel/connected_channel.c +7 -5
  86. data/src/core/lib/channel/http_client_filter.c +34 -8
  87. data/src/core/lib/channel/http_client_filter.h +1 -1
  88. data/src/core/lib/channel/http_server_filter.c +21 -12
  89. data/src/core/lib/compression/{compression_algorithm.c → compression.c} +22 -21
  90. data/src/core/lib/http/httpcli.c +81 -59
  91. data/src/core/lib/http/httpcli.h +11 -15
  92. data/src/core/lib/http/httpcli_security_connector.c +5 -3
  93. data/src/core/lib/http/parser.c +127 -118
  94. data/src/core/lib/http/parser.h +11 -6
  95. data/src/core/lib/iomgr/closure.c +20 -16
  96. data/src/core/lib/iomgr/closure.h +19 -15
  97. data/src/core/lib/iomgr/endpoint.h +1 -1
  98. data/src/core/lib/iomgr/endpoint_pair_posix.c +2 -2
  99. data/src/core/lib/iomgr/error.c +535 -0
  100. data/src/core/lib/iomgr/error.h +192 -0
  101. data/src/core/lib/iomgr/ev_poll_and_epoll_posix.c +190 -83
  102. data/src/core/lib/iomgr/ev_poll_posix.c +1267 -0
  103. data/src/{ruby/ext/grpc/rb_signal.h → core/lib/iomgr/ev_poll_posix.h} +7 -5
  104. data/src/core/lib/iomgr/ev_posix.c +104 -14
  105. data/src/core/lib/iomgr/ev_posix.h +17 -7
  106. data/src/core/lib/iomgr/exec_ctx.c +25 -7
  107. data/src/core/lib/iomgr/exec_ctx.h +27 -8
  108. data/src/core/lib/iomgr/executor.c +2 -2
  109. data/src/core/lib/iomgr/executor.h +1 -1
  110. data/src/core/lib/iomgr/iocp_windows.c +2 -41
  111. data/src/core/lib/iomgr/iocp_windows.h +0 -8
  112. data/src/core/lib/iomgr/iomgr.c +5 -4
  113. data/src/core/lib/iomgr/iomgr_posix.c +5 -1
  114. data/src/core/lib/iomgr/iomgr_windows.c +1 -1
  115. data/src/core/lib/{support → iomgr}/load_file.c +15 -17
  116. data/src/core/lib/{support → iomgr}/load_file.h +8 -7
  117. data/src/core/lib/iomgr/polling_entity.c +104 -0
  118. data/src/core/lib/iomgr/polling_entity.h +81 -0
  119. data/src/core/lib/iomgr/pollset.h +6 -5
  120. data/src/core/lib/iomgr/pollset_set_windows.c +4 -1
  121. data/src/core/lib/iomgr/pollset_windows.c +10 -6
  122. data/src/core/lib/iomgr/resolve_address.h +5 -9
  123. data/src/core/lib/iomgr/resolve_address_posix.c +55 -38
  124. data/src/core/lib/iomgr/resolve_address_windows.c +51 -37
  125. data/src/core/lib/iomgr/sockaddr.h +2 -2
  126. data/src/core/lib/iomgr/{sockaddr_win32.h → sockaddr_windows.h} +3 -3
  127. data/src/core/lib/iomgr/socket_utils_common_posix.c +92 -45
  128. data/src/core/lib/iomgr/socket_utils_posix.h +19 -12
  129. data/src/core/lib/iomgr/socket_windows.c +61 -2
  130. data/src/core/lib/iomgr/socket_windows.h +13 -0
  131. data/src/core/lib/iomgr/tcp_client_posix.c +54 -39
  132. data/src/core/lib/iomgr/tcp_client_windows.c +34 -34
  133. data/src/core/lib/iomgr/tcp_posix.c +43 -39
  134. data/src/core/lib/iomgr/tcp_server.h +5 -3
  135. data/src/core/lib/iomgr/tcp_server_posix.c +103 -64
  136. data/src/core/lib/iomgr/tcp_server_windows.c +114 -101
  137. data/src/core/lib/iomgr/tcp_windows.c +45 -50
  138. data/src/core/lib/iomgr/tcp_windows.h +1 -1
  139. data/src/core/lib/iomgr/timer.c +26 -13
  140. data/src/core/lib/iomgr/udp_server.c +28 -4
  141. data/src/core/lib/iomgr/udp_server.h +5 -1
  142. data/src/core/lib/iomgr/unix_sockets_posix.c +8 -7
  143. data/src/core/lib/iomgr/unix_sockets_posix.h +2 -1
  144. data/src/core/lib/iomgr/unix_sockets_posix_noop.c +4 -2
  145. data/src/core/lib/iomgr/wakeup_fd_eventfd.c +15 -5
  146. data/src/core/lib/iomgr/wakeup_fd_pipe.c +13 -9
  147. data/src/core/lib/iomgr/wakeup_fd_posix.c +6 -6
  148. data/src/core/lib/iomgr/wakeup_fd_posix.h +9 -6
  149. data/src/core/lib/iomgr/workqueue.h +5 -4
  150. data/src/core/lib/iomgr/workqueue_posix.c +40 -26
  151. data/src/core/lib/iomgr/workqueue_windows.c +2 -2
  152. data/src/core/lib/profiling/basic_timers.c +2 -2
  153. data/src/core/lib/security/{security_context.c → context/security_context.c} +1 -1
  154. data/src/core/lib/security/{security_context.h → context/security_context.h} +4 -4
  155. data/src/core/lib/security/credentials/composite/composite_credentials.c +263 -0
  156. data/src/core/lib/security/credentials/composite/composite_credentials.h +72 -0
  157. data/src/core/lib/security/credentials/credentials.c +233 -0
  158. data/src/core/lib/security/{credentials.h → credentials/credentials.h} +19 -157
  159. data/src/core/lib/security/{credentials_metadata.c → credentials/credentials_metadata.c} +1 -1
  160. data/src/core/lib/security/credentials/fake/fake_credentials.c +139 -0
  161. data/src/core/lib/security/credentials/fake/fake_credentials.h +56 -0
  162. data/src/core/lib/security/{credentials_posix.c → credentials/google_default/credentials_posix.c} +1 -1
  163. data/src/core/lib/security/{credentials_win32.c → credentials/google_default/credentials_windows.c} +3 -3
  164. data/src/core/lib/security/{google_default_credentials.c → credentials/google_default/google_default_credentials.c} +93 -35
  165. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +46 -0
  166. data/src/core/lib/security/credentials/iam/iam_credentials.c +85 -0
  167. data/src/core/lib/security/credentials/iam/iam_credentials.h +44 -0
  168. data/src/core/lib/security/{json_token.c → credentials/jwt/json_token.c} +10 -101
  169. data/src/core/lib/security/{json_token.h → credentials/jwt/json_token.h} +3 -33
  170. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +160 -0
  171. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +62 -0
  172. data/src/core/lib/security/{jwt_verifier.c → credentials/jwt/jwt_verifier.c} +35 -15
  173. data/src/core/lib/security/{jwt_verifier.h → credentials/jwt/jwt_verifier.h} +3 -3
  174. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +433 -0
  175. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +109 -0
  176. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +129 -0
  177. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +45 -0
  178. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +240 -0
  179. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +48 -0
  180. data/src/core/lib/security/{auth_filters.h → transport/auth_filters.h} +3 -3
  181. data/src/core/lib/security/{client_auth_filter.c → transport/client_auth_filter.c} +27 -20
  182. data/src/core/lib/security/{handshake.c → transport/handshake.c} +77 -45
  183. data/src/core/lib/security/{handshake.h → transport/handshake.h} +9 -11
  184. data/src/core/lib/security/{secure_endpoint.c → transport/secure_endpoint.c} +19 -12
  185. data/src/core/lib/security/{secure_endpoint.h → transport/secure_endpoint.h} +3 -3
  186. data/src/core/lib/security/{security_connector.c → transport/security_connector.c} +26 -17
  187. data/src/core/lib/security/{security_connector.h → transport/security_connector.h} +8 -8
  188. data/src/core/lib/security/{server_auth_filter.c → transport/server_auth_filter.c} +24 -16
  189. data/src/core/lib/security/transport/tsi_error.c +40 -0
  190. data/src/core/lib/security/transport/tsi_error.h +42 -0
  191. data/src/core/lib/security/{b64.c → util/b64.c} +1 -1
  192. data/src/core/lib/security/{b64.h → util/b64.h} +3 -3
  193. data/src/core/lib/security/util/json_util.c +61 -0
  194. data/src/core/lib/security/util/json_util.h +55 -0
  195. data/src/core/lib/support/avl.c +11 -0
  196. data/src/core/lib/support/cpu_windows.c +2 -2
  197. data/src/core/lib/support/{env_win32.c → env_windows.c} +3 -3
  198. data/src/core/lib/support/log.c +3 -1
  199. data/src/core/lib/support/log_linux.c +2 -2
  200. data/src/core/lib/support/{log_win32.c → log_windows.c} +4 -4
  201. data/src/core/lib/support/murmur_hash.c +3 -5
  202. data/src/core/lib/support/string.c +10 -0
  203. data/src/core/lib/support/string.h +4 -0
  204. data/src/core/lib/support/{string_util_win32.c → string_util_windows.c} +3 -3
  205. data/src/core/lib/support/{string_win32.c → string_windows.c} +2 -2
  206. data/src/core/lib/support/{string_win32.h → string_windows.h} +5 -5
  207. data/src/core/lib/support/subprocess_windows.c +1 -1
  208. data/src/core/lib/support/{sync_win32.c → sync_windows.c} +2 -2
  209. data/src/core/lib/support/{thd_win32.c → thd_windows.c} +2 -2
  210. data/src/core/lib/support/{time_win32.c → time_windows.c} +2 -2
  211. data/src/core/lib/support/tmpfile_msys.c +1 -1
  212. data/src/core/lib/support/{tmpfile_win32.c → tmpfile_windows.c} +3 -3
  213. data/src/core/lib/surface/alarm.c +2 -2
  214. data/src/core/lib/surface/byte_buffer_reader.c +13 -6
  215. data/src/core/lib/surface/call.c +323 -123
  216. data/src/core/lib/surface/call.h +2 -0
  217. data/src/core/lib/surface/call_log_batch.c +1 -1
  218. data/src/core/lib/surface/channel.c +64 -15
  219. data/src/core/lib/surface/channel.h +9 -0
  220. data/src/core/lib/surface/channel_ping.c +3 -3
  221. data/src/core/lib/surface/completion_queue.c +75 -19
  222. data/src/core/lib/surface/completion_queue.h +7 -2
  223. data/src/core/lib/surface/init.c +2 -1
  224. data/src/core/lib/surface/init_secure.c +4 -4
  225. data/src/core/lib/surface/lame_client.c +12 -8
  226. data/src/core/lib/surface/server.c +213 -120
  227. data/src/core/lib/surface/server.h +1 -0
  228. data/src/core/lib/surface/version.c +1 -1
  229. data/src/core/lib/transport/connectivity_state.c +40 -18
  230. data/src/core/lib/transport/connectivity_state.h +4 -1
  231. data/src/core/lib/transport/metadata.c +23 -23
  232. data/src/core/lib/transport/metadata.h +4 -0
  233. data/src/core/lib/transport/metadata_batch.c +9 -0
  234. data/src/core/lib/transport/metadata_batch.h +3 -0
  235. data/src/core/lib/transport/static_metadata.c +6 -5
  236. data/src/core/lib/transport/static_metadata.h +64 -60
  237. data/src/core/lib/transport/transport.c +24 -12
  238. data/src/core/lib/transport/transport.h +6 -5
  239. data/src/core/lib/transport/transport_impl.h +4 -0
  240. data/src/core/lib/transport/transport_op_string.c +2 -2
  241. data/src/core/plugin_registry/grpc_plugin_registry.c +4 -0
  242. data/src/ruby/bin/math_services.rb +41 -2
  243. data/src/ruby/ext/grpc/rb_call.c +42 -40
  244. data/src/ruby/ext/grpc/rb_channel.c +1 -1
  245. data/src/ruby/ext/grpc/rb_completion_queue.c +59 -6
  246. data/src/ruby/ext/grpc/rb_completion_queue.h +1 -1
  247. data/src/ruby/ext/grpc/rb_grpc.c +1 -3
  248. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +12 -2
  249. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +21 -5
  250. data/src/ruby/ext/grpc/rb_loader.c +1 -1
  251. data/src/ruby/ext/grpc/rb_server.c +5 -3
  252. data/src/ruby/lib/grpc.rb +0 -3
  253. data/src/ruby/lib/grpc/errors.rb +3 -2
  254. data/src/ruby/lib/grpc/generic/active_call.rb +32 -42
  255. data/src/ruby/lib/grpc/generic/bidi_call.rb +20 -0
  256. data/src/ruby/lib/grpc/generic/client_stub.rb +31 -54
  257. data/src/ruby/lib/grpc/generic/rpc_desc.rb +4 -4
  258. data/src/ruby/lib/grpc/generic/rpc_server.rb +12 -23
  259. data/src/ruby/lib/grpc/generic/service.rb +8 -8
  260. data/src/ruby/lib/grpc/version.rb +1 -1
  261. data/src/ruby/pb/grpc/health/v1/health_services.rb +30 -2
  262. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb +34 -4
  263. data/src/ruby/pb/grpc/testing/metrics_services.rb +39 -2
  264. data/src/ruby/pb/src/proto/grpc/testing/empty.rb +15 -0
  265. data/src/ruby/pb/src/proto/grpc/testing/messages.rb +84 -0
  266. data/src/ruby/pb/src/proto/grpc/testing/test.rb +14 -0
  267. data/src/ruby/pb/src/proto/grpc/testing/test_services.rb +110 -0
  268. data/src/ruby/pb/test/client.rb +5 -2
  269. data/src/ruby/spec/generic/active_call_spec.rb +3 -2
  270. data/src/ruby/spec/generic/client_stub_spec.rb +27 -24
  271. data/src/ruby/spec/generic/rpc_desc_spec.rb +11 -11
  272. data/src/ruby/spec/generic/rpc_server_spec.rb +42 -61
  273. data/src/ruby/spec/pb/health/checker_spec.rb +3 -5
  274. metadata +86 -48
  275. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h +0 -182
  276. data/src/core/lib/security/credentials.c +0 -1296
  277. data/src/ruby/lib/grpc/signals.rb +0 -69
@@ -0,0 +1,232 @@
1
+ /*
2
+ *
3
+ * Copyright 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
+
34
+ #include "src/core/ext/transport/chttp2/transport/bin_decoder.h"
35
+ #include <grpc/support/alloc.h>
36
+ #include <grpc/support/log.h>
37
+ #include "src/core/lib/support/string.h"
38
+
39
+ static uint8_t decode_table[] = {
40
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
41
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
42
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
43
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 62, 0x40, 0x40, 0x40, 63,
44
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0x40, 0x40,
45
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0, 1, 2, 3, 4, 5, 6,
46
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
47
+ 19, 20, 21, 22, 23, 24, 25, 0x40, 0x40, 0x40, 0x40, 0x40,
48
+ 0x40, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
49
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
50
+ 49, 50, 51, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
51
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
52
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
53
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
54
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
55
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
56
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
57
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
58
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
59
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
60
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
61
+ 0x40, 0x40, 0x40, 0x40};
62
+
63
+ static const uint8_t tail_xtra[4] = {0, 0, 1, 2};
64
+
65
+ static bool input_is_valid(uint8_t *input_ptr, size_t length) {
66
+ size_t i;
67
+
68
+ for (i = 0; i < length; ++i) {
69
+ if ((decode_table[input_ptr[i]] & 0xC0) != 0) {
70
+ gpr_log(GPR_ERROR,
71
+ "Base64 decoding failed, invalid character '%c' in base64 "
72
+ "input.\n",
73
+ (char)(*input_ptr));
74
+ return false;
75
+ }
76
+ }
77
+ return true;
78
+ }
79
+
80
+ #define COMPOSE_OUTPUT_BYTE_0(input_ptr) \
81
+ (uint8_t)((decode_table[input_ptr[0]] << 2) | \
82
+ (decode_table[input_ptr[1]] >> 4))
83
+
84
+ #define COMPOSE_OUTPUT_BYTE_1(input_ptr) \
85
+ (uint8_t)((decode_table[input_ptr[1]] << 4) | \
86
+ (decode_table[input_ptr[2]] >> 2))
87
+
88
+ #define COMPOSE_OUTPUT_BYTE_2(input_ptr) \
89
+ (uint8_t)((decode_table[input_ptr[2]] << 6) | decode_table[input_ptr[3]])
90
+
91
+ bool grpc_base64_decode_partial(struct grpc_base64_decode_context *ctx) {
92
+ size_t input_tail;
93
+
94
+ if (ctx->input_cur > ctx->input_end || ctx->output_cur > ctx->output_end) {
95
+ return false;
96
+ }
97
+
98
+ // Process a block of 4 input characters and 3 output bytes
99
+ while (ctx->input_end >= ctx->input_cur + 4 &&
100
+ ctx->output_end >= ctx->output_cur + 3) {
101
+ if (!input_is_valid(ctx->input_cur, 4)) return false;
102
+ ctx->output_cur[0] = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur);
103
+ ctx->output_cur[1] = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur);
104
+ ctx->output_cur[2] = COMPOSE_OUTPUT_BYTE_2(ctx->input_cur);
105
+ ctx->output_cur += 3;
106
+ ctx->input_cur += 4;
107
+ }
108
+
109
+ // Process the tail of input data
110
+ input_tail = (size_t)(ctx->input_end - ctx->input_cur);
111
+ if (input_tail == 4) {
112
+ // Process the input data with pad chars
113
+ if (ctx->input_cur[3] == '=') {
114
+ if (ctx->input_cur[2] == '=' && ctx->output_end >= ctx->output_cur + 1) {
115
+ if (!input_is_valid(ctx->input_cur, 2)) return false;
116
+ *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur);
117
+ ctx->input_cur += 4;
118
+ } else if (ctx->output_end >= ctx->output_cur + 2) {
119
+ if (!input_is_valid(ctx->input_cur, 3)) return false;
120
+ *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur);
121
+ *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur);
122
+ ;
123
+ ctx->input_cur += 4;
124
+ }
125
+ }
126
+
127
+ } else if (ctx->contains_tail && input_tail > 1) {
128
+ // Process the input data without pad chars, but constains_tail is set
129
+ if (ctx->output_end >= ctx->output_cur + tail_xtra[input_tail]) {
130
+ if (!input_is_valid(ctx->input_cur, input_tail)) return false;
131
+ switch (input_tail) {
132
+ case 3:
133
+ ctx->output_cur[1] = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur);
134
+ case 2:
135
+ ctx->output_cur[0] = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur);
136
+ }
137
+ ctx->output_cur += tail_xtra[input_tail];
138
+ ctx->input_cur += input_tail;
139
+ }
140
+ }
141
+
142
+ return true;
143
+ }
144
+
145
+ gpr_slice grpc_chttp2_base64_decode(gpr_slice input) {
146
+ size_t input_length = GPR_SLICE_LENGTH(input);
147
+ size_t output_length = input_length / 4 * 3;
148
+ struct grpc_base64_decode_context ctx;
149
+ gpr_slice output;
150
+
151
+ if (input_length % 4 != 0) {
152
+ gpr_log(GPR_ERROR,
153
+ "Base64 decoding failed, input of "
154
+ "grpc_chttp2_base64_decode has a length of %d, which is not a "
155
+ "multiple of 4.\n",
156
+ (int)input_length);
157
+ return gpr_empty_slice();
158
+ }
159
+
160
+ if (input_length > 0) {
161
+ uint8_t *input_end = GPR_SLICE_END_PTR(input);
162
+ if (*(--input_end) == '=') {
163
+ output_length--;
164
+ if (*(--input_end) == '=') {
165
+ output_length--;
166
+ }
167
+ }
168
+ }
169
+ output = gpr_slice_malloc(output_length);
170
+
171
+ ctx.input_cur = GPR_SLICE_START_PTR(input);
172
+ ctx.input_end = GPR_SLICE_END_PTR(input);
173
+ ctx.output_cur = GPR_SLICE_START_PTR(output);
174
+ ctx.output_end = GPR_SLICE_END_PTR(output);
175
+ ctx.contains_tail = false;
176
+
177
+ if (!grpc_base64_decode_partial(&ctx)) {
178
+ char *s = gpr_dump_slice(input, GPR_DUMP_ASCII);
179
+ gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
180
+ gpr_free(s);
181
+ gpr_slice_unref(output);
182
+ return gpr_empty_slice();
183
+ }
184
+ GPR_ASSERT(ctx.output_cur == GPR_SLICE_END_PTR(output));
185
+ GPR_ASSERT(ctx.input_cur == GPR_SLICE_END_PTR(input));
186
+ return output;
187
+ }
188
+
189
+ gpr_slice grpc_chttp2_base64_decode_with_length(gpr_slice input,
190
+ size_t output_length) {
191
+ size_t input_length = GPR_SLICE_LENGTH(input);
192
+ gpr_slice output = gpr_slice_malloc(output_length);
193
+ struct grpc_base64_decode_context ctx;
194
+
195
+ // The length of a base64 string cannot be 4 * n + 1
196
+ if (input_length % 4 == 1) {
197
+ gpr_log(GPR_ERROR,
198
+ "Base64 decoding failed, input of "
199
+ "grpc_chttp2_base64_decode_with_length has a length of %d, which "
200
+ "has a tail of 1 byte.\n",
201
+ (int)input_length);
202
+ gpr_slice_unref(output);
203
+ return gpr_empty_slice();
204
+ }
205
+
206
+ if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) {
207
+ gpr_log(GPR_ERROR,
208
+ "Base64 decoding failed, output_length %d is longer "
209
+ "than the max possible output length %d.\n",
210
+ (int)output_length,
211
+ (int)(input_length / 4 * 3 + tail_xtra[input_length % 4]));
212
+ gpr_slice_unref(output);
213
+ return gpr_empty_slice();
214
+ }
215
+
216
+ ctx.input_cur = GPR_SLICE_START_PTR(input);
217
+ ctx.input_end = GPR_SLICE_END_PTR(input);
218
+ ctx.output_cur = GPR_SLICE_START_PTR(output);
219
+ ctx.output_end = GPR_SLICE_END_PTR(output);
220
+ ctx.contains_tail = true;
221
+
222
+ if (!grpc_base64_decode_partial(&ctx)) {
223
+ char *s = gpr_dump_slice(input, GPR_DUMP_ASCII);
224
+ gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
225
+ gpr_free(s);
226
+ gpr_slice_unref(output);
227
+ return gpr_empty_slice();
228
+ }
229
+ GPR_ASSERT(ctx.output_cur == GPR_SLICE_END_PTR(output));
230
+ GPR_ASSERT(ctx.input_cur <= GPR_SLICE_END_PTR(input));
231
+ return output;
232
+ }
@@ -31,40 +31,36 @@
31
31
  *
32
32
  */
33
33
 
34
- #include <ruby/ruby.h>
35
- #include <signal.h>
36
- #include <stdbool.h>
37
-
38
- #include <grpc/support/log.h>
34
+ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H
35
+ #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H
39
36
 
40
- #include "rb_grpc.h"
37
+ #include <grpc/support/slice.h>
38
+ #include <stdbool.h>
41
39
 
42
- static void (*old_sigint_handler)(int);
43
- static void (*old_sigterm_handler)(int);
40
+ struct grpc_base64_decode_context {
41
+ /* input/output: */
42
+ uint8_t *input_cur;
43
+ uint8_t *input_end;
44
+ uint8_t *output_cur;
45
+ uint8_t *output_end;
46
+ /* Indicate if the decoder should handle the tail of input data*/
47
+ bool contains_tail;
48
+ };
44
49
 
45
- static volatile bool signal_received = false;
50
+ /* base64 decode a grpc_base64_decode_context util either input_end is reached
51
+ or output_end is reached. When input_end is reached, (input_end - input_cur)
52
+ is less than 4. When output_end is reached, (output_end - output_cur) is less
53
+ than 3. Returns false if decoding is failed. */
54
+ bool grpc_base64_decode_partial(struct grpc_base64_decode_context *ctx);
46
55
 
47
- /* This has to be handled at the C level instead of Ruby, because Ruby signal
48
- * handlers are constrained to run in the main interpreter thread. If that main
49
- * thread is blocked on grpc_completion_queue_pluck, the signal handlers will
50
- * never run */
51
- static void handle_signal(int signum) {
52
- signal_received = true;
53
- if (signum == SIGINT) {
54
- old_sigint_handler(signum);
55
- } else if (signum == SIGTERM) {
56
- old_sigterm_handler(signum);
57
- }
58
- }
56
+ /* base64 decode a slice with pad chars. Returns a new slice, does not take
57
+ ownership of the input. Returns an empty slice if decoding is failed. */
58
+ gpr_slice grpc_chttp2_base64_decode(gpr_slice input);
59
59
 
60
- static VALUE grpc_rb_signal_received(VALUE self) {
61
- (void)self;
62
- return signal_received ? Qtrue : Qfalse;
63
- }
60
+ /* base64 decode a slice without pad chars, data length is needed. Returns a new
61
+ slice, does not take ownership of the input. Returns an empty slice if
62
+ decoding is failed. */
63
+ gpr_slice grpc_chttp2_base64_decode_with_length(gpr_slice input,
64
+ size_t output_length);
64
65
 
65
- void Init_grpc_signals() {
66
- old_sigint_handler = signal(SIGINT, handle_signal);
67
- old_sigterm_handler = signal(SIGTERM, handle_signal);
68
- rb_define_singleton_method(grpc_rb_mGrpcCore, "signal_received?",
69
- grpc_rb_signal_received, 0);
70
- }
66
+ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */
@@ -47,6 +47,7 @@
47
47
  #include "src/core/ext/transport/chttp2/transport/internal.h"
48
48
  #include "src/core/ext/transport/chttp2/transport/status_conversion.h"
49
49
  #include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
50
+ #include "src/core/lib/http/parser.h"
50
51
  #include "src/core/lib/profiling/timers.h"
51
52
  #include "src/core/lib/support/string.h"
52
53
  #include "src/core/lib/transport/static_metadata.h"
@@ -56,6 +57,8 @@
56
57
  #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
57
58
  #define MAX_WINDOW 0x7fffffffu
58
59
 
60
+ #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
61
+
59
62
  #define MAX_CLIENT_STREAM_ID 0x7fffffffu
60
63
 
61
64
  int grpc_http_trace = 0;
@@ -65,8 +68,8 @@ int grpc_flowctl_trace = 0;
65
68
  ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
66
69
  writing)))
67
70
 
68
- #define TRANSPORT_FROM_PARSING(tw) \
69
- ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
71
+ #define TRANSPORT_FROM_PARSING(tp) \
72
+ ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
70
73
  parsing)))
71
74
 
72
75
  #define TRANSPORT_FROM_GLOBAL(tg) \
@@ -82,19 +85,17 @@ int grpc_flowctl_trace = 0;
82
85
  static const grpc_transport_vtable vtable;
83
86
 
84
87
  /* forward declarations of various callbacks that we'll build closures around */
85
- static void writing_action(grpc_exec_ctx *exec_ctx, void *t,
86
- bool iomgr_success_ignored);
87
- static void reading_action(grpc_exec_ctx *exec_ctx, void *t,
88
- bool iomgr_success_ignored);
89
- static void parsing_action(grpc_exec_ctx *exec_ctx, void *t,
90
- bool iomgr_success_ignored);
88
+ static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
89
+ static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
90
+ static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
91
91
 
92
92
  /** Set a transport level setting, and push it to our peer */
93
93
  static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
94
94
  uint32_t value);
95
95
 
96
96
  /** Start disconnection chain */
97
- static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
97
+ static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
98
+ grpc_error *error);
98
99
 
99
100
  /** Perform a transport_op */
100
101
  static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
@@ -105,7 +106,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
105
106
  static void cancel_from_api(grpc_exec_ctx *exec_ctx,
106
107
  grpc_chttp2_transport_global *transport_global,
107
108
  grpc_chttp2_stream_global *stream_global,
108
- grpc_status_code status);
109
+ grpc_status_code status,
110
+ gpr_slice *optional_message);
109
111
 
110
112
  static void close_from_api(grpc_exec_ctx *exec_ctx,
111
113
  grpc_chttp2_transport_global *transport_global,
@@ -131,7 +133,7 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
131
133
 
132
134
  static void connectivity_state_set(
133
135
  grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
134
- grpc_connectivity_state state, const char *reason);
136
+ grpc_connectivity_state state, grpc_error *error, const char *reason);
135
137
 
136
138
  static void check_read_ops(grpc_exec_ctx *exec_ctx,
137
139
  grpc_chttp2_transport_global *transport_global);
@@ -145,7 +147,9 @@ static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
145
147
  grpc_chttp2_stream *s,
146
148
  void *byte_stream);
147
149
  static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
148
- grpc_chttp2_stream_global *stream_global);
150
+ grpc_chttp2_transport_global *transport_global,
151
+ grpc_chttp2_stream_global *stream_global,
152
+ grpc_error *error);
149
153
 
150
154
  /*******************************************************************************
151
155
  * CONSTRUCTION/DESTRUCTION/REFCOUNTING
@@ -159,6 +163,8 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
159
163
 
160
164
  GPR_ASSERT(t->ep == NULL);
161
165
 
166
+ gpr_slice_unref(t->optional_drop_message);
167
+
162
168
  gpr_slice_buffer_destroy(&t->global.qbuf);
163
169
 
164
170
  gpr_slice_buffer_destroy(&t->writing.outbuf);
@@ -188,7 +194,8 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
188
194
  and maybe they hold resources that need to be freed */
189
195
  while (t->global.pings.next != &t->global.pings) {
190
196
  grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
191
- grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, false, NULL);
197
+ grpc_exec_ctx_sched(exec_ctx, ping->on_recv,
198
+ GRPC_ERROR_CREATE("Transport closed"), NULL);
192
199
  ping->next->prev = ping->prev;
193
200
  ping->prev->next = ping->next;
194
201
  gpr_free(ping);
@@ -257,7 +264,9 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
257
264
  t->parsing.is_client = is_client;
258
265
  t->parsing.deframe_state =
259
266
  is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
267
+ t->parsing.is_first_frame = true;
260
268
  t->writing.is_client = is_client;
269
+ t->optional_drop_message = gpr_empty_slice();
261
270
  grpc_connectivity_state_init(
262
271
  &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
263
272
  is_client ? "client_transport" : "server_transport");
@@ -311,6 +320,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
311
320
  push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
312
321
  }
313
322
  push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW);
323
+ push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
324
+ DEFAULT_MAX_HEADER_LIST_SIZE);
314
325
 
315
326
  if (channel_args) {
316
327
  for (i = 0; i < channel_args->num_args; i++) {
@@ -378,6 +389,18 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
378
389
  &t->writing.hpack_compressor,
379
390
  (uint32_t)channel_args->args[i].value.integer);
380
391
  }
392
+ } else if (0 == strcmp(channel_args->args[i].key,
393
+ GRPC_ARG_MAX_METADATA_SIZE)) {
394
+ if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
395
+ gpr_log(GPR_ERROR, "%s: must be an integer",
396
+ GRPC_ARG_MAX_METADATA_SIZE);
397
+ } else if (channel_args->args[i].value.integer < 0) {
398
+ gpr_log(GPR_ERROR, "%s: must be non-negative",
399
+ GRPC_ARG_MAX_METADATA_SIZE);
400
+ } else {
401
+ push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
402
+ (uint32_t)channel_args->args[i].value.integer);
403
+ }
381
404
  }
382
405
  }
383
406
  }
@@ -388,7 +411,7 @@ static void destroy_transport_locked(grpc_exec_ctx *exec_ctx,
388
411
  grpc_chttp2_stream *s_ignored,
389
412
  void *arg_ignored) {
390
413
  t->destroying = 1;
391
- drop_connection(exec_ctx, t);
414
+ drop_connection(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
392
415
  }
393
416
 
394
417
  static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
@@ -424,12 +447,11 @@ static void destroy_endpoint(grpc_exec_ctx *exec_ctx,
424
447
 
425
448
  static void close_transport_locked(grpc_exec_ctx *exec_ctx,
426
449
  grpc_chttp2_transport *t,
427
- grpc_chttp2_stream *s_ignored,
428
- void *arg_ignored) {
450
+ grpc_error *error) {
429
451
  if (!t->closed) {
430
452
  t->closed = 1;
431
- connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_FATAL_FAILURE,
432
- "close_transport");
453
+ connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN,
454
+ GRPC_ERROR_REF(error), "close_transport");
433
455
  if (t->ep) {
434
456
  allow_endpoint_shutdown_locked(exec_ctx, t);
435
457
  }
@@ -442,6 +464,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
442
464
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
443
465
  }
444
466
  }
467
+ GRPC_ERROR_UNREF(error);
445
468
  }
446
469
 
447
470
  #ifdef GRPC_STREAM_REFCOUNT_DEBUG
@@ -510,7 +533,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
510
533
  [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
511
534
  *t->accepting_stream = s;
512
535
  grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s);
513
- s->global.in_stream_map = 1;
536
+ s->global.in_stream_map = true;
514
537
  }
515
538
 
516
539
  grpc_chttp2_run_with_global_lock(exec_ctx, t, s, finish_init_stream_locked,
@@ -530,7 +553,9 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx,
530
553
  s->global.id == 0);
531
554
  GPR_ASSERT(!s->global.in_stream_map);
532
555
  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
533
- close_transport_locked(exec_ctx, t, NULL, NULL);
556
+ close_transport_locked(
557
+ exec_ctx, t,
558
+ GRPC_ERROR_CREATE("Last stream closed after sending goaway"));
534
559
  }
535
560
  if (!t->executor.parsing_active && s->global.id) {
536
561
  GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
@@ -619,12 +644,11 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
619
644
 
620
645
  for (;;) {
621
646
  if (!t->executor.writing_active && !t->closed &&
622
- grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing,
623
- t->executor.parsing_active)) {
647
+ grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) {
624
648
  t->executor.writing_active = 1;
625
649
  REF_TRANSPORT(t, "writing");
626
650
  prevent_endpoint_shutdown(t);
627
- grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, true, NULL);
651
+ grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL);
628
652
  }
629
653
  check_read_ops(exec_ctx, &t->global);
630
654
 
@@ -735,12 +759,12 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
735
759
  grpc_chttp2_transport *t,
736
760
  grpc_chttp2_stream *s_ignored,
737
761
  void *a) {
738
- bool success = (bool)(uintptr_t)a;
762
+ grpc_error *error = a;
739
763
 
740
764
  allow_endpoint_shutdown_locked(exec_ctx, t);
741
765
 
742
- if (!success) {
743
- drop_connection(exec_ctx, t);
766
+ if (error != GRPC_ERROR_NONE) {
767
+ drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
744
768
  }
745
769
 
746
770
  grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
@@ -748,7 +772,8 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
748
772
  grpc_chttp2_stream_global *stream_global;
749
773
  while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
750
774
  &stream_global)) {
751
- fail_pending_writes(exec_ctx, stream_global);
775
+ fail_pending_writes(exec_ctx, &t->global, stream_global,
776
+ GRPC_ERROR_REF(error));
752
777
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
753
778
  }
754
779
 
@@ -761,18 +786,18 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
761
786
  }
762
787
 
763
788
  UNREF_TRANSPORT(exec_ctx, t, "writing");
789
+ GRPC_ERROR_UNREF(error);
764
790
  }
765
791
 
766
792
  void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
767
- void *transport_writing, bool success) {
793
+ void *transport_writing, grpc_error *error) {
768
794
  grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
769
- grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL,
770
- terminate_writing_with_lock,
771
- (void *)(uintptr_t)success, 0);
795
+ grpc_chttp2_run_with_global_lock(
796
+ exec_ctx, t, NULL, terminate_writing_with_lock, GRPC_ERROR_REF(error), 0);
772
797
  }
773
798
 
774
799
  static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
775
- bool iomgr_success_ignored) {
800
+ grpc_error *error) {
776
801
  grpc_chttp2_transport *t = gt;
777
802
  GPR_TIMER_BEGIN("writing_action", 0);
778
803
  grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
@@ -785,11 +810,19 @@ void grpc_chttp2_add_incoming_goaway(
785
810
  char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
786
811
  GRPC_CHTTP2_IF_TRACING(
787
812
  gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg));
788
- gpr_free(msg);
789
813
  gpr_slice_unref(goaway_text);
790
814
  transport_global->seen_goaway = 1;
791
- connectivity_state_set(exec_ctx, transport_global, GRPC_CHANNEL_FATAL_FAILURE,
792
- "got_goaway");
815
+ /* lie: use transient failure from the transport to indicate goaway has been
816
+ * received */
817
+ connectivity_state_set(
818
+ exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
819
+ grpc_error_set_str(
820
+ grpc_error_set_int(GRPC_ERROR_CREATE("GOAWAY received"),
821
+ GRPC_ERROR_INT_HTTP2_ERROR,
822
+ (intptr_t)goaway_error),
823
+ GRPC_ERROR_STR_RAW_BYTES, msg),
824
+ "got_goaway");
825
+ gpr_free(msg);
793
826
  }
794
827
 
795
828
  static void maybe_start_some_streams(
@@ -818,9 +851,9 @@ static void maybe_start_some_streams(
818
851
  transport_global->next_stream_id += 2;
819
852
 
820
853
  if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
821
- connectivity_state_set(exec_ctx, transport_global,
822
- GRPC_CHANNEL_TRANSIENT_FAILURE,
823
- "no_more_stream_ids");
854
+ connectivity_state_set(
855
+ exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
856
+ GRPC_ERROR_CREATE("Stream IDs exhausted"), "no_more_stream_ids");
824
857
  }
825
858
 
826
859
  stream_global->outgoing_window =
@@ -834,7 +867,7 @@ static void maybe_start_some_streams(
834
867
  grpc_chttp2_stream_map_add(
835
868
  &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map,
836
869
  stream_global->id, STREAM_FROM_GLOBAL(stream_global));
837
- stream_global->in_stream_map = 1;
870
+ stream_global->in_stream_map = true;
838
871
  transport_global->concurrent_stream_count++;
839
872
  grpc_chttp2_become_writable(transport_global, stream_global);
840
873
  }
@@ -843,39 +876,45 @@ static void maybe_start_some_streams(
843
876
  grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
844
877
  &stream_global)) {
845
878
  cancel_from_api(exec_ctx, transport_global, stream_global,
846
- GRPC_STATUS_UNAVAILABLE);
879
+ GRPC_STATUS_UNAVAILABLE, NULL);
847
880
  }
848
881
  }
849
882
 
850
883
  #define CLOSURE_BARRIER_STATS_BIT (1 << 0)
851
- #define CLOSURE_BARRIER_FAILURE_BIT (1 << 1)
852
884
  #define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
853
885
 
854
886
  static grpc_closure *add_closure_barrier(grpc_closure *closure) {
855
- closure->final_data += CLOSURE_BARRIER_FIRST_REF_BIT;
887
+ closure->next_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT;
856
888
  return closure;
857
889
  }
858
890
 
859
- void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
860
- grpc_chttp2_stream_global *stream_global,
861
- grpc_closure **pclosure, int success) {
891
+ void grpc_chttp2_complete_closure_step(
892
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
893
+ grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure,
894
+ grpc_error *error) {
862
895
  grpc_closure *closure = *pclosure;
863
896
  if (closure == NULL) {
897
+ GRPC_ERROR_UNREF(error);
864
898
  return;
865
899
  }
866
- closure->final_data -= CLOSURE_BARRIER_FIRST_REF_BIT;
867
- if (!success) {
868
- closure->final_data |= CLOSURE_BARRIER_FAILURE_BIT;
900
+ closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
901
+ if (error != GRPC_ERROR_NONE) {
902
+ if (closure->error == GRPC_ERROR_NONE) {
903
+ closure->error =
904
+ GRPC_ERROR_CREATE("Error in HTTP transport completing operation");
905
+ closure->error = grpc_error_set_str(
906
+ closure->error, GRPC_ERROR_STR_TARGET_ADDRESS,
907
+ TRANSPORT_FROM_GLOBAL(transport_global)->peer_string);
908
+ }
909
+ closure->error = grpc_error_add_child(closure->error, error);
869
910
  }
870
- if (closure->final_data < CLOSURE_BARRIER_FIRST_REF_BIT) {
871
- if (closure->final_data & CLOSURE_BARRIER_STATS_BIT) {
911
+ if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
912
+ if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
872
913
  grpc_transport_move_stats(&stream_global->stats,
873
914
  stream_global->collecting_stats);
874
915
  stream_global->collecting_stats = NULL;
875
916
  }
876
- grpc_exec_ctx_enqueue(
877
- exec_ctx, closure,
878
- (closure->final_data & CLOSURE_BARRIER_FAILURE_BIT) == 0, NULL);
917
+ grpc_exec_ctx_sched(exec_ctx, closure, closure->error, NULL);
879
918
  }
880
919
  *pclosure = NULL;
881
920
  }
@@ -893,7 +932,7 @@ static int contains_non_ok_status(
893
932
  return 0;
894
933
  }
895
934
 
896
- static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool success) {}
935
+ static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
897
936
 
898
937
  static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
899
938
  grpc_chttp2_transport *t,
@@ -910,17 +949,18 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
910
949
  }
911
950
  /* use final_data as a barrier until enqueue time; the inital counter is
912
951
  dropped at the end of this function */
913
- on_complete->final_data = CLOSURE_BARRIER_FIRST_REF_BIT;
952
+ on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
953
+ on_complete->error = GRPC_ERROR_NONE;
914
954
 
915
955
  if (op->collect_stats != NULL) {
916
956
  GPR_ASSERT(stream_global->collecting_stats == NULL);
917
957
  stream_global->collecting_stats = op->collect_stats;
918
- on_complete->final_data |= CLOSURE_BARRIER_STATS_BIT;
958
+ on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
919
959
  }
920
960
 
921
961
  if (op->cancel_with_status != GRPC_STATUS_OK) {
922
962
  cancel_from_api(exec_ctx, transport_global, stream_global,
923
- op->cancel_with_status);
963
+ op->cancel_with_status, op->optional_close_message);
924
964
  }
925
965
 
926
966
  if (op->close_with_status != GRPC_STATUS_OK) {
@@ -933,24 +973,40 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
933
973
  stream_global->send_initial_metadata_finished =
934
974
  add_closure_barrier(on_complete);
935
975
  stream_global->send_initial_metadata = op->send_initial_metadata;
936
- if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
937
- stream_global->seen_error = 1;
938
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
939
- }
940
- if (!stream_global->write_closed) {
941
- if (transport_global->is_client) {
942
- GPR_ASSERT(stream_global->id == 0);
943
- grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
944
- stream_global);
945
- maybe_start_some_streams(exec_ctx, transport_global);
976
+ const size_t metadata_size =
977
+ grpc_metadata_batch_size(op->send_initial_metadata);
978
+ const size_t metadata_peer_limit =
979
+ transport_global->settings[GRPC_PEER_SETTINGS]
980
+ [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
981
+ if (metadata_size > metadata_peer_limit) {
982
+ gpr_log(GPR_DEBUG,
983
+ "to-be-sent initial metadata size exceeds peer limit "
984
+ "(%" PRIuPTR " vs. %" PRIuPTR ")",
985
+ metadata_size, metadata_peer_limit);
986
+ cancel_from_api(exec_ctx, transport_global, stream_global,
987
+ GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
988
+ } else {
989
+ if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
990
+ stream_global->seen_error = true;
991
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
992
+ }
993
+ if (!stream_global->write_closed) {
994
+ if (transport_global->is_client) {
995
+ GPR_ASSERT(stream_global->id == 0);
996
+ grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
997
+ stream_global);
998
+ maybe_start_some_streams(exec_ctx, transport_global);
999
+ } else {
1000
+ GPR_ASSERT(stream_global->id != 0);
1001
+ grpc_chttp2_become_writable(transport_global, stream_global);
1002
+ }
946
1003
  } else {
947
- GPR_ASSERT(stream_global->id != 0);
948
- grpc_chttp2_become_writable(transport_global, stream_global);
1004
+ grpc_chttp2_complete_closure_step(
1005
+ exec_ctx, transport_global, stream_global,
1006
+ &stream_global->send_initial_metadata_finished,
1007
+ GRPC_ERROR_CREATE(
1008
+ "Attempt to send initial metadata after stream was closed"));
949
1009
  }
950
- } else {
951
- grpc_chttp2_complete_closure_step(
952
- exec_ctx, stream_global,
953
- &stream_global->send_initial_metadata_finished, 0);
954
1010
  }
955
1011
  }
956
1012
 
@@ -960,7 +1016,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
960
1016
  stream_global->send_message_finished = add_closure_barrier(on_complete);
961
1017
  if (stream_global->write_closed) {
962
1018
  grpc_chttp2_complete_closure_step(
963
- exec_ctx, stream_global, &stream_global->send_message_finished, 0);
1019
+ exec_ctx, transport_global, stream_global,
1020
+ &stream_global->send_message_finished,
1021
+ GRPC_ERROR_CREATE("Attempt to send message after stream was closed"));
964
1022
  } else {
965
1023
  stream_global->send_message = op->send_message;
966
1024
  if (stream_global->id != 0) {
@@ -974,19 +1032,37 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
974
1032
  stream_global->send_trailing_metadata_finished =
975
1033
  add_closure_barrier(on_complete);
976
1034
  stream_global->send_trailing_metadata = op->send_trailing_metadata;
977
- if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) {
978
- stream_global->seen_error = 1;
979
- grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
980
- }
981
- if (stream_global->write_closed) {
982
- grpc_chttp2_complete_closure_step(
983
- exec_ctx, stream_global,
984
- &stream_global->send_trailing_metadata_finished,
985
- grpc_metadata_batch_is_empty(op->send_trailing_metadata));
986
- } else if (stream_global->id != 0) {
987
- /* TODO(ctiller): check if there's flow control for any outstanding
988
- bytes before going writable */
989
- grpc_chttp2_become_writable(transport_global, stream_global);
1035
+ const size_t metadata_size =
1036
+ grpc_metadata_batch_size(op->send_trailing_metadata);
1037
+ const size_t metadata_peer_limit =
1038
+ transport_global->settings[GRPC_PEER_SETTINGS]
1039
+ [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
1040
+ if (metadata_size > metadata_peer_limit) {
1041
+ gpr_log(GPR_DEBUG,
1042
+ "to-be-sent trailing metadata size exceeds peer limit "
1043
+ "(%" PRIuPTR " vs. %" PRIuPTR ")",
1044
+ metadata_size, metadata_peer_limit);
1045
+ cancel_from_api(exec_ctx, transport_global, stream_global,
1046
+ GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
1047
+ } else {
1048
+ if (contains_non_ok_status(transport_global,
1049
+ op->send_trailing_metadata)) {
1050
+ stream_global->seen_error = true;
1051
+ grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1052
+ }
1053
+ if (stream_global->write_closed) {
1054
+ grpc_chttp2_complete_closure_step(
1055
+ exec_ctx, transport_global, stream_global,
1056
+ &stream_global->send_trailing_metadata_finished,
1057
+ grpc_metadata_batch_is_empty(op->send_trailing_metadata)
1058
+ ? GRPC_ERROR_NONE
1059
+ : GRPC_ERROR_CREATE("Attempt to send trailing metadata after "
1060
+ "stream was closed"));
1061
+ } else if (stream_global->id != 0) {
1062
+ /* TODO(ctiller): check if there's flow control for any outstanding
1063
+ bytes before going writable */
1064
+ grpc_chttp2_become_writable(transport_global, stream_global);
1065
+ }
990
1066
  }
991
1067
  }
992
1068
 
@@ -1017,10 +1093,12 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
1017
1093
  stream_global->recv_trailing_metadata_finished =
1018
1094
  add_closure_barrier(on_complete);
1019
1095
  stream_global->recv_trailing_metadata = op->recv_trailing_metadata;
1096
+ stream_global->final_metadata_requested = true;
1020
1097
  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1021
1098
  }
1022
1099
 
1023
- grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &on_complete, 1);
1100
+ grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
1101
+ &on_complete, GRPC_ERROR_NONE);
1024
1102
 
1025
1103
  GPR_TIMER_END("perform_stream_op_locked", 0);
1026
1104
  }
@@ -1057,7 +1135,7 @@ static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1057
1135
  for (ping = transport_global->pings.next; ping != &transport_global->pings;
1058
1136
  ping = ping->next) {
1059
1137
  if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
1060
- grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, true, NULL);
1138
+ grpc_exec_ctx_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE, NULL);
1061
1139
  ping->next->prev = ping->prev;
1062
1140
  ping->prev->next = ping->next;
1063
1141
  gpr_free(ping);
@@ -1079,7 +1157,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1079
1157
  grpc_chttp2_stream *s_unused,
1080
1158
  void *stream_op) {
1081
1159
  grpc_transport_op *op = stream_op;
1082
- bool close_transport = op->disconnect;
1160
+ grpc_error *close_transport = op->disconnect_with_error;
1083
1161
 
1084
1162
  /* If there's a set_accept_stream ensure that we're not parsing
1085
1163
  to avoid changing things out from underneath */
@@ -1090,7 +1168,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1090
1168
  return;
1091
1169
  }
1092
1170
 
1093
- grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
1171
+ grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
1094
1172
 
1095
1173
  if (op->on_connectivity_state_change != NULL) {
1096
1174
  grpc_connectivity_state_notify_on_state_change(
@@ -1104,7 +1182,9 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1104
1182
  t->global.last_incoming_stream_id,
1105
1183
  (uint32_t)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
1106
1184
  gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
1107
- close_transport = !grpc_chttp2_has_streams(t);
1185
+ close_transport = grpc_chttp2_has_streams(t)
1186
+ ? GRPC_ERROR_NONE
1187
+ : GRPC_ERROR_CREATE("GOAWAY sent");
1108
1188
  }
1109
1189
 
1110
1190
  if (op->set_accept_stream) {
@@ -1125,8 +1205,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1125
1205
  send_ping_locked(t, op->send_ping);
1126
1206
  }
1127
1207
 
1128
- if (close_transport) {
1129
- close_transport_locked(exec_ctx, t, NULL, NULL);
1208
+ if (close_transport != GRPC_ERROR_NONE) {
1209
+ close_transport_locked(exec_ctx, t, close_transport);
1130
1210
  }
1131
1211
  }
1132
1212
 
@@ -1149,15 +1229,26 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
1149
1229
  grpc_chttp2_list_pop_check_read_ops(transport_global, &stream_global)) {
1150
1230
  if (stream_global->recv_initial_metadata_ready != NULL &&
1151
1231
  stream_global->published_initial_metadata) {
1232
+ if (stream_global->seen_error) {
1233
+ while ((bs = grpc_chttp2_incoming_frame_queue_pop(
1234
+ &stream_global->incoming_frames)) != NULL) {
1235
+ incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1236
+ }
1237
+ if (stream_global->exceeded_metadata_size) {
1238
+ cancel_from_api(exec_ctx, transport_global, stream_global,
1239
+ GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
1240
+ }
1241
+ }
1152
1242
  grpc_chttp2_incoming_metadata_buffer_publish(
1153
1243
  &stream_global->received_initial_metadata,
1154
1244
  stream_global->recv_initial_metadata);
1155
- grpc_exec_ctx_enqueue(
1156
- exec_ctx, stream_global->recv_initial_metadata_ready, true, NULL);
1245
+ grpc_exec_ctx_sched(exec_ctx, stream_global->recv_initial_metadata_ready,
1246
+ GRPC_ERROR_NONE, NULL);
1157
1247
  stream_global->recv_initial_metadata_ready = NULL;
1158
1248
  }
1159
1249
  if (stream_global->recv_message_ready != NULL) {
1160
- while (stream_global->seen_error &&
1250
+ while (stream_global->final_metadata_requested &&
1251
+ stream_global->seen_error &&
1161
1252
  (bs = grpc_chttp2_incoming_frame_queue_pop(
1162
1253
  &stream_global->incoming_frames)) != NULL) {
1163
1254
  incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
@@ -1166,30 +1257,35 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
1166
1257
  *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
1167
1258
  &stream_global->incoming_frames);
1168
1259
  GPR_ASSERT(*stream_global->recv_message != NULL);
1169
- grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
1170
- NULL);
1260
+ grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
1261
+ GRPC_ERROR_NONE, NULL);
1171
1262
  stream_global->recv_message_ready = NULL;
1172
1263
  } else if (stream_global->published_trailing_metadata) {
1173
1264
  *stream_global->recv_message = NULL;
1174
- grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
1175
- NULL);
1265
+ grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
1266
+ GRPC_ERROR_NONE, NULL);
1176
1267
  stream_global->recv_message_ready = NULL;
1177
1268
  }
1178
1269
  }
1179
1270
  if (stream_global->recv_trailing_metadata_finished != NULL &&
1180
1271
  stream_global->read_closed && stream_global->write_closed) {
1181
- while (stream_global->seen_error &&
1182
- (bs = grpc_chttp2_incoming_frame_queue_pop(
1183
- &stream_global->incoming_frames)) != NULL) {
1184
- incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1272
+ if (stream_global->seen_error) {
1273
+ while ((bs = grpc_chttp2_incoming_frame_queue_pop(
1274
+ &stream_global->incoming_frames)) != NULL) {
1275
+ incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1276
+ }
1277
+ if (stream_global->exceeded_metadata_size) {
1278
+ cancel_from_api(exec_ctx, transport_global, stream_global,
1279
+ GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
1280
+ }
1185
1281
  }
1186
1282
  if (stream_global->all_incoming_byte_streams_finished) {
1187
1283
  grpc_chttp2_incoming_metadata_buffer_publish(
1188
1284
  &stream_global->received_trailing_metadata,
1189
1285
  stream_global->recv_trailing_metadata);
1190
1286
  grpc_chttp2_complete_closure_step(
1191
- exec_ctx, stream_global,
1192
- &stream_global->recv_trailing_metadata_finished, 1);
1287
+ exec_ctx, transport_global, stream_global,
1288
+ &stream_global->recv_trailing_metadata_finished, GRPC_ERROR_NONE);
1193
1289
  }
1194
1290
  }
1195
1291
  }
@@ -1205,7 +1301,7 @@ static void decrement_active_streams_locked(
1205
1301
  }
1206
1302
 
1207
1303
  static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1208
- uint32_t id) {
1304
+ uint32_t id, grpc_error *error) {
1209
1305
  size_t new_stream_count;
1210
1306
  grpc_chttp2_stream *s =
1211
1307
  grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
@@ -1213,19 +1309,22 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1213
1309
  s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
1214
1310
  }
1215
1311
  GPR_ASSERT(s);
1216
- s->global.in_stream_map = 0;
1312
+ s->global.in_stream_map = false;
1217
1313
  if (t->parsing.incoming_stream == &s->parsing) {
1218
1314
  t->parsing.incoming_stream = NULL;
1219
1315
  grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing);
1220
1316
  }
1221
1317
  if (s->parsing.data_parser.parsing_frame != NULL) {
1222
1318
  grpc_chttp2_incoming_byte_stream_finished(
1223
- exec_ctx, s->parsing.data_parser.parsing_frame, 0, 0);
1319
+ exec_ctx, s->parsing.data_parser.parsing_frame,
1320
+ GRPC_ERROR_CREATE_REFERENCING("Stream removed", &error, 1), 0);
1224
1321
  s->parsing.data_parser.parsing_frame = NULL;
1225
1322
  }
1226
1323
 
1227
1324
  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
1228
- close_transport_locked(exec_ctx, t, NULL, NULL);
1325
+ close_transport_locked(
1326
+ exec_ctx, t,
1327
+ GRPC_ERROR_CREATE("Last stream closed after sending GOAWAY"));
1229
1328
  }
1230
1329
  if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
1231
1330
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
@@ -1238,12 +1337,14 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1238
1337
  t->global.concurrent_stream_count = (uint32_t)new_stream_count;
1239
1338
  maybe_start_some_streams(exec_ctx, &t->global);
1240
1339
  }
1340
+ GRPC_ERROR_UNREF(error);
1241
1341
  }
1242
1342
 
1243
1343
  static void cancel_from_api(grpc_exec_ctx *exec_ctx,
1244
1344
  grpc_chttp2_transport_global *transport_global,
1245
1345
  grpc_chttp2_stream_global *stream_global,
1246
- grpc_status_code status) {
1346
+ grpc_status_code status,
1347
+ gpr_slice *optional_message) {
1247
1348
  if (!stream_global->read_closed || !stream_global->write_closed) {
1248
1349
  if (stream_global->id != 0) {
1249
1350
  gpr_slice_buffer_add(
@@ -1253,15 +1354,21 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
1253
1354
  (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status),
1254
1355
  &stream_global->stats.outgoing));
1255
1356
  }
1357
+
1358
+ if (optional_message) {
1359
+ gpr_slice_ref(*optional_message);
1360
+ }
1256
1361
  grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
1257
- NULL);
1362
+ optional_message);
1258
1363
  }
1259
1364
  if (status != GRPC_STATUS_OK && !stream_global->seen_error) {
1260
- stream_global->seen_error = 1;
1365
+ stream_global->seen_error = true;
1261
1366
  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1262
1367
  }
1263
- grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1264
- 1);
1368
+ grpc_chttp2_mark_stream_closed(
1369
+ exec_ctx, transport_global, stream_global, 1, 1,
1370
+ grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
1371
+ GRPC_ERROR_INT_GRPC_STATUS, status));
1265
1372
  }
1266
1373
 
1267
1374
  void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
@@ -1269,7 +1376,7 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
1269
1376
  grpc_chttp2_stream_global *stream_global,
1270
1377
  grpc_status_code status, gpr_slice *slice) {
1271
1378
  if (status != GRPC_STATUS_OK) {
1272
- stream_global->seen_error = 1;
1379
+ stream_global->seen_error = true;
1273
1380
  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1274
1381
  }
1275
1382
  /* stream_global->recv_trailing_metadata_finished gives us a
@@ -1293,7 +1400,7 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
1293
1400
  GRPC_MDSTR_GRPC_MESSAGE,
1294
1401
  grpc_mdstr_from_slice(gpr_slice_ref(*slice))));
1295
1402
  }
1296
- stream_global->published_trailing_metadata = 1;
1403
+ stream_global->published_trailing_metadata = true;
1297
1404
  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1298
1405
  }
1299
1406
  if (slice) {
@@ -1302,40 +1409,45 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
1302
1409
  }
1303
1410
 
1304
1411
  static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
1305
- grpc_chttp2_stream_global *stream_global) {
1412
+ grpc_chttp2_transport_global *transport_global,
1413
+ grpc_chttp2_stream_global *stream_global,
1414
+ grpc_error *error) {
1306
1415
  grpc_chttp2_complete_closure_step(
1307
- exec_ctx, stream_global, &stream_global->send_initial_metadata_finished,
1308
- 0);
1416
+ exec_ctx, transport_global, stream_global,
1417
+ &stream_global->send_initial_metadata_finished, GRPC_ERROR_REF(error));
1309
1418
  grpc_chttp2_complete_closure_step(
1310
- exec_ctx, stream_global, &stream_global->send_trailing_metadata_finished,
1311
- 0);
1312
- grpc_chttp2_complete_closure_step(exec_ctx, stream_global,
1313
- &stream_global->send_message_finished, 0);
1419
+ exec_ctx, transport_global, stream_global,
1420
+ &stream_global->send_trailing_metadata_finished, GRPC_ERROR_REF(error));
1421
+ grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
1422
+ &stream_global->send_message_finished,
1423
+ error);
1314
1424
  }
1315
1425
 
1316
1426
  void grpc_chttp2_mark_stream_closed(
1317
1427
  grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
1318
- grpc_chttp2_stream_global *stream_global, int close_reads,
1319
- int close_writes) {
1428
+ grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
1429
+ grpc_error *error) {
1320
1430
  if (stream_global->read_closed && stream_global->write_closed) {
1321
1431
  /* already closed */
1432
+ GRPC_ERROR_UNREF(error);
1322
1433
  return;
1323
1434
  }
1324
1435
  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1325
1436
  if (close_reads && !stream_global->read_closed) {
1326
- stream_global->read_closed = 1;
1327
- stream_global->published_initial_metadata = 1;
1328
- stream_global->published_trailing_metadata = 1;
1437
+ stream_global->read_closed = true;
1438
+ stream_global->published_initial_metadata = true;
1439
+ stream_global->published_trailing_metadata = true;
1329
1440
  decrement_active_streams_locked(exec_ctx, transport_global, stream_global);
1330
1441
  }
1331
1442
  if (close_writes && !stream_global->write_closed) {
1332
- stream_global->write_closed = 1;
1443
+ stream_global->write_closed = true;
1333
1444
  if (TRANSPORT_FROM_GLOBAL(transport_global)->executor.writing_active) {
1334
1445
  GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes");
1335
1446
  grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
1336
1447
  stream_global);
1337
1448
  } else {
1338
- fail_pending_writes(exec_ctx, stream_global);
1449
+ fail_pending_writes(exec_ctx, transport_global, stream_global,
1450
+ GRPC_ERROR_REF(error));
1339
1451
  }
1340
1452
  }
1341
1453
  if (stream_global->read_closed && stream_global->write_closed) {
@@ -1346,11 +1458,12 @@ void grpc_chttp2_mark_stream_closed(
1346
1458
  } else {
1347
1459
  if (stream_global->id != 0) {
1348
1460
  remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
1349
- stream_global->id);
1461
+ stream_global->id, GRPC_ERROR_REF(error));
1350
1462
  }
1351
1463
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
1352
1464
  }
1353
1465
  }
1466
+ GRPC_ERROR_UNREF(error);
1354
1467
  }
1355
1468
 
1356
1469
  static void close_from_api(grpc_exec_ctx *exec_ctx,
@@ -1366,104 +1479,118 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1366
1479
 
1367
1480
  GPR_ASSERT(status >= 0 && (int)status < 100);
1368
1481
 
1369
- GPR_ASSERT(stream_global->id != 0);
1370
-
1371
- /* Hand roll a header block.
1372
- This is unnecessarily ugly - at some point we should find a more elegant
1373
- solution.
1374
- It's complicated by the fact that our send machinery would be dead by the
1375
- time we got around to sending this, so instead we ignore HPACK compression
1376
- and just write the uncompressed bytes onto the wire. */
1377
- status_hdr = gpr_slice_malloc(15 + (status >= 10));
1378
- p = GPR_SLICE_START_PTR(status_hdr);
1379
- *p++ = 0x40; /* literal header */
1380
- *p++ = 11; /* len(grpc-status) */
1381
- *p++ = 'g';
1382
- *p++ = 'r';
1383
- *p++ = 'p';
1384
- *p++ = 'c';
1385
- *p++ = '-';
1386
- *p++ = 's';
1387
- *p++ = 't';
1388
- *p++ = 'a';
1389
- *p++ = 't';
1390
- *p++ = 'u';
1391
- *p++ = 's';
1392
- if (status < 10) {
1393
- *p++ = 1;
1394
- *p++ = (uint8_t)('0' + status);
1395
- } else {
1396
- *p++ = 2;
1397
- *p++ = (uint8_t)('0' + (status / 10));
1398
- *p++ = (uint8_t)('0' + (status % 10));
1399
- }
1400
- GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
1401
- len += (uint32_t)GPR_SLICE_LENGTH(status_hdr);
1402
-
1403
- if (optional_message) {
1404
- GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127);
1405
- message_pfx = gpr_slice_malloc(15);
1406
- p = GPR_SLICE_START_PTR(message_pfx);
1407
- *p++ = 0x40;
1408
- *p++ = 12; /* len(grpc-message) */
1482
+ if (stream_global->id != 0 && !transport_global->is_client) {
1483
+ /* Hand roll a header block.
1484
+ This is unnecessarily ugly - at some point we should find a more elegant
1485
+ solution.
1486
+ It's complicated by the fact that our send machinery would be dead by the
1487
+ time we got around to sending this, so instead we ignore HPACK
1488
+ compression
1489
+ and just write the uncompressed bytes onto the wire. */
1490
+ status_hdr = gpr_slice_malloc(15 + (status >= 10));
1491
+ p = GPR_SLICE_START_PTR(status_hdr);
1492
+ *p++ = 0x40; /* literal header */
1493
+ *p++ = 11; /* len(grpc-status) */
1409
1494
  *p++ = 'g';
1410
1495
  *p++ = 'r';
1411
1496
  *p++ = 'p';
1412
1497
  *p++ = 'c';
1413
1498
  *p++ = '-';
1414
- *p++ = 'm';
1415
- *p++ = 'e';
1416
- *p++ = 's';
1417
1499
  *p++ = 's';
1500
+ *p++ = 't';
1418
1501
  *p++ = 'a';
1419
- *p++ = 'g';
1420
- *p++ = 'e';
1421
- *p++ = (uint8_t)GPR_SLICE_LENGTH(*optional_message);
1422
- GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
1423
- len += (uint32_t)GPR_SLICE_LENGTH(message_pfx);
1424
- len += (uint32_t)GPR_SLICE_LENGTH(*optional_message);
1425
- }
1426
-
1427
- hdr = gpr_slice_malloc(9);
1428
- p = GPR_SLICE_START_PTR(hdr);
1429
- *p++ = (uint8_t)(len >> 16);
1430
- *p++ = (uint8_t)(len >> 8);
1431
- *p++ = (uint8_t)(len);
1432
- *p++ = GRPC_CHTTP2_FRAME_HEADER;
1433
- *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
1434
- *p++ = (uint8_t)(stream_global->id >> 24);
1435
- *p++ = (uint8_t)(stream_global->id >> 16);
1436
- *p++ = (uint8_t)(stream_global->id >> 8);
1437
- *p++ = (uint8_t)(stream_global->id);
1438
- GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr));
1439
-
1440
- gpr_slice_buffer_add(&transport_global->qbuf, hdr);
1441
- gpr_slice_buffer_add(&transport_global->qbuf, status_hdr);
1442
- if (optional_message) {
1443
- gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
1444
- gpr_slice_buffer_add(&transport_global->qbuf,
1445
- gpr_slice_ref(*optional_message));
1446
- }
1502
+ *p++ = 't';
1503
+ *p++ = 'u';
1504
+ *p++ = 's';
1505
+ if (status < 10) {
1506
+ *p++ = 1;
1507
+ *p++ = (uint8_t)('0' + status);
1508
+ } else {
1509
+ *p++ = 2;
1510
+ *p++ = (uint8_t)('0' + (status / 10));
1511
+ *p++ = (uint8_t)('0' + (status % 10));
1512
+ }
1513
+ GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
1514
+ len += (uint32_t)GPR_SLICE_LENGTH(status_hdr);
1515
+
1516
+ if (optional_message) {
1517
+ GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127);
1518
+ message_pfx = gpr_slice_malloc(15);
1519
+ p = GPR_SLICE_START_PTR(message_pfx);
1520
+ *p++ = 0x40;
1521
+ *p++ = 12; /* len(grpc-message) */
1522
+ *p++ = 'g';
1523
+ *p++ = 'r';
1524
+ *p++ = 'p';
1525
+ *p++ = 'c';
1526
+ *p++ = '-';
1527
+ *p++ = 'm';
1528
+ *p++ = 'e';
1529
+ *p++ = 's';
1530
+ *p++ = 's';
1531
+ *p++ = 'a';
1532
+ *p++ = 'g';
1533
+ *p++ = 'e';
1534
+ *p++ = (uint8_t)GPR_SLICE_LENGTH(*optional_message);
1535
+ GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
1536
+ len += (uint32_t)GPR_SLICE_LENGTH(message_pfx);
1537
+ len += (uint32_t)GPR_SLICE_LENGTH(*optional_message);
1538
+ }
1447
1539
 
1448
- gpr_slice_buffer_add(
1449
- &transport_global->qbuf,
1450
- grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR,
1451
- &stream_global->stats.outgoing));
1540
+ hdr = gpr_slice_malloc(9);
1541
+ p = GPR_SLICE_START_PTR(hdr);
1542
+ *p++ = (uint8_t)(len >> 16);
1543
+ *p++ = (uint8_t)(len >> 8);
1544
+ *p++ = (uint8_t)(len);
1545
+ *p++ = GRPC_CHTTP2_FRAME_HEADER;
1546
+ *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
1547
+ *p++ = (uint8_t)(stream_global->id >> 24);
1548
+ *p++ = (uint8_t)(stream_global->id >> 16);
1549
+ *p++ = (uint8_t)(stream_global->id >> 8);
1550
+ *p++ = (uint8_t)(stream_global->id);
1551
+ GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr));
1552
+
1553
+ gpr_slice_buffer_add(&transport_global->qbuf, hdr);
1554
+ gpr_slice_buffer_add(&transport_global->qbuf, status_hdr);
1555
+ if (optional_message) {
1556
+ gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
1557
+ gpr_slice_buffer_add(&transport_global->qbuf,
1558
+ gpr_slice_ref(*optional_message));
1559
+ }
1452
1560
 
1453
- if (optional_message) {
1454
- gpr_slice_ref(*optional_message);
1561
+ gpr_slice_buffer_add(
1562
+ &transport_global->qbuf,
1563
+ grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR,
1564
+ &stream_global->stats.outgoing));
1565
+
1566
+ if (optional_message) {
1567
+ gpr_slice_ref(*optional_message);
1568
+ }
1455
1569
  }
1570
+
1456
1571
  grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
1457
1572
  optional_message);
1573
+ grpc_error *err = GRPC_ERROR_CREATE("Stream closed");
1574
+ err = grpc_error_set_int(err, GRPC_ERROR_INT_GRPC_STATUS, status);
1575
+ if (optional_message) {
1576
+ char *str =
1577
+ gpr_dump_slice(*optional_message, GPR_DUMP_HEX | GPR_DUMP_ASCII);
1578
+ err = grpc_error_set_str(err, GRPC_ERROR_STR_GRPC_MESSAGE, str);
1579
+ gpr_free(str);
1580
+ }
1458
1581
  grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1459
- 1);
1582
+ 1, err);
1460
1583
  }
1461
1584
 
1462
1585
  static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
1463
1586
  void *user_data,
1464
1587
  grpc_chttp2_stream_global *stream_global) {
1588
+ grpc_chttp2_transport *transport = TRANSPORT_FROM_GLOBAL(transport_global);
1465
1589
  cancel_from_api(user_data, transport_global, stream_global,
1466
- GRPC_STATUS_UNAVAILABLE);
1590
+ GRPC_STATUS_UNAVAILABLE,
1591
+ GPR_SLICE_IS_EMPTY(transport->optional_drop_message)
1592
+ ? NULL
1593
+ : &transport->optional_drop_message);
1467
1594
  }
1468
1595
 
1469
1596
  static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
@@ -1471,8 +1598,9 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
1471
1598
  grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb);
1472
1599
  }
1473
1600
 
1474
- static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
1475
- close_transport_locked(exec_ctx, t, NULL, NULL);
1601
+ static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1602
+ grpc_error *error) {
1603
+ close_transport_locked(exec_ctx, t, error);
1476
1604
  end_all_the_calls(exec_ctx, t);
1477
1605
  }
1478
1606
 
@@ -1503,20 +1631,22 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
1503
1631
  static void reading_action_locked(grpc_exec_ctx *exec_ctx,
1504
1632
  grpc_chttp2_transport *t,
1505
1633
  grpc_chttp2_stream *s_unused, void *arg);
1506
- static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success);
1634
+ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
1635
+ grpc_error *error);
1507
1636
  static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1508
1637
  grpc_chttp2_transport *t,
1509
1638
  grpc_chttp2_stream *s_unused, void *arg);
1510
1639
  static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1511
1640
  grpc_chttp2_stream *s_unused, void *arg);
1512
1641
 
1513
- static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
1642
+ static void reading_action(grpc_exec_ctx *exec_ctx, void *tp,
1643
+ grpc_error *error) {
1514
1644
  /* Control flow:
1515
1645
  reading_action_locked ->
1516
1646
  (parse_unlocked -> post_parse_locked)? ->
1517
1647
  post_reading_action_locked */
1518
1648
  grpc_chttp2_run_with_global_lock(exec_ctx, tp, NULL, reading_action_locked,
1519
- (void *)(uintptr_t)success, 0);
1649
+ GRPC_ERROR_REF(error), 0);
1520
1650
  }
1521
1651
 
1522
1652
  static void reading_action_locked(grpc_exec_ctx *exec_ctx,
@@ -1524,7 +1654,7 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx,
1524
1654
  grpc_chttp2_stream *s_unused, void *arg) {
1525
1655
  grpc_chttp2_transport_global *transport_global = &t->global;
1526
1656
  grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
1527
- bool success = (bool)(uintptr_t)arg;
1657
+ grpc_error *error = arg;
1528
1658
 
1529
1659
  GPR_ASSERT(!t->executor.parsing_active);
1530
1660
  if (!t->closed) {
@@ -1533,27 +1663,73 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx,
1533
1663
  grpc_chttp2_stream_map_move_into(&t->new_stream_map,
1534
1664
  &t->parsing_stream_map);
1535
1665
  grpc_chttp2_prepare_to_read(transport_global, transport_parsing);
1536
- grpc_exec_ctx_enqueue(exec_ctx, &t->parsing_action, success, NULL);
1666
+ grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL);
1537
1667
  } else {
1538
1668
  post_reading_action_locked(exec_ctx, t, s_unused, arg);
1539
1669
  }
1540
1670
  }
1541
1671
 
1542
- static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
1672
+ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
1673
+ grpc_chttp2_transport *t) {
1674
+ grpc_http_parser parser;
1675
+ size_t i = 0;
1676
+ grpc_error *error = GRPC_ERROR_NONE;
1677
+ grpc_http_response response;
1678
+ memset(&response, 0, sizeof(response));
1679
+
1680
+ grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
1681
+
1682
+ grpc_error *parse_error = GRPC_ERROR_NONE;
1683
+ for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) {
1684
+ parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i]);
1685
+ }
1686
+ if (parse_error == GRPC_ERROR_NONE &&
1687
+ (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
1688
+ error = grpc_error_set_int(
1689
+ GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
1690
+ GRPC_ERROR_INT_HTTP_STATUS, response.status);
1691
+ }
1692
+ GRPC_ERROR_UNREF(parse_error);
1693
+
1694
+ grpc_http_parser_destroy(&parser);
1695
+ grpc_http_response_destroy(&response);
1696
+ return error;
1697
+ }
1698
+
1699
+ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
1700
+ grpc_error *error) {
1543
1701
  grpc_chttp2_transport *t = arg;
1544
1702
  GPR_TIMER_BEGIN("reading_action.parse", 0);
1545
1703
  size_t i = 0;
1546
- for (; i < t->read_buffer.count &&
1547
- grpc_chttp2_perform_read(exec_ctx, &t->parsing,
1548
- t->read_buffer.slices[i]);
1549
- i++)
1550
- ;
1704
+ grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
1705
+ GRPC_ERROR_NONE};
1706
+ for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
1707
+ errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing,
1708
+ t->read_buffer.slices[i]);
1709
+ };
1551
1710
  if (i != t->read_buffer.count) {
1552
- success = false;
1711
+ gpr_slice_unref(t->optional_drop_message);
1712
+ errors[2] = try_http_parsing(exec_ctx, t);
1713
+ if (errors[2] != GRPC_ERROR_NONE) {
1714
+ t->optional_drop_message = gpr_slice_from_copied_string(
1715
+ "Connection dropped: received http1.x response");
1716
+ } else {
1717
+ t->optional_drop_message = gpr_slice_from_copied_string(
1718
+ "Connection dropped: received unparseable response");
1719
+ }
1720
+ }
1721
+ grpc_error *err =
1722
+ errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE &&
1723
+ errors[2] == GRPC_ERROR_NONE
1724
+ ? GRPC_ERROR_NONE
1725
+ : GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
1726
+ GPR_ARRAY_SIZE(errors));
1727
+ for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
1728
+ GRPC_ERROR_UNREF(errors[i]);
1553
1729
  }
1554
1730
  GPR_TIMER_END("reading_action.parse", 0);
1555
- grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked,
1556
- (void *)(uintptr_t)success, 0);
1731
+ grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, err,
1732
+ 0);
1557
1733
  }
1558
1734
 
1559
1735
  static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@@ -1590,7 +1766,8 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1590
1766
  GPR_ASSERT(stream_global->in_stream_map);
1591
1767
  GPR_ASSERT(stream_global->write_closed);
1592
1768
  GPR_ASSERT(stream_global->read_closed);
1593
- remove_stream(exec_ctx, t, stream_global->id);
1769
+ remove_stream(exec_ctx, t, stream_global->id,
1770
+ GRPC_ERROR_CREATE("Stream removed"));
1594
1771
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
1595
1772
  }
1596
1773
 
@@ -1601,10 +1778,13 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1601
1778
  grpc_chttp2_transport *t,
1602
1779
  grpc_chttp2_stream *s_unused,
1603
1780
  void *arg) {
1604
- bool success = (bool)(uintptr_t)arg;
1781
+ grpc_error *error = arg;
1605
1782
  bool keep_reading = false;
1606
- if (!success || t->closed) {
1607
- drop_connection(exec_ctx, t);
1783
+ if (error == GRPC_ERROR_NONE && t->closed) {
1784
+ error = GRPC_ERROR_CREATE("Transport closed");
1785
+ }
1786
+ if (error != GRPC_ERROR_NONE) {
1787
+ drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
1608
1788
  t->endpoint_reading = 0;
1609
1789
  if (!t->executor.writing_active && t->ep) {
1610
1790
  grpc_endpoint_destroy(exec_ctx, t->ep);
@@ -1626,6 +1806,8 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1626
1806
  } else {
1627
1807
  UNREF_TRANSPORT(exec_ctx, t, "reading_action");
1628
1808
  }
1809
+
1810
+ GRPC_LOG_IF_ERROR("close_transport", error);
1629
1811
  }
1630
1812
 
1631
1813
  /*******************************************************************************
@@ -1634,13 +1816,13 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1634
1816
 
1635
1817
  static void connectivity_state_set(
1636
1818
  grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
1637
- grpc_connectivity_state state, const char *reason) {
1819
+ grpc_connectivity_state state, grpc_error *error, const char *reason) {
1638
1820
  GRPC_CHTTP2_IF_TRACING(
1639
1821
  gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
1640
1822
  grpc_connectivity_state_set(
1641
1823
  exec_ctx,
1642
1824
  &TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker,
1643
- state, reason);
1825
+ state, error, reason);
1644
1826
  }
1645
1827
 
1646
1828
  /*******************************************************************************
@@ -1672,6 +1854,13 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1672
1854
  add_to_pollset_locked, pollset, 0);
1673
1855
  }
1674
1856
 
1857
+ static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1858
+ grpc_stream *gs, grpc_pollset_set *pollset_set) {
1859
+ grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt,
1860
+ (grpc_chttp2_stream *)gs,
1861
+ add_to_pollset_set_locked, pollset_set, 0);
1862
+ }
1863
+
1675
1864
  /*******************************************************************************
1676
1865
  * BYTE STREAM
1677
1866
  */
@@ -1679,6 +1868,7 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1679
1868
  static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
1680
1869
  grpc_chttp2_incoming_byte_stream *bs) {
1681
1870
  if (gpr_unref(&bs->refs)) {
1871
+ GRPC_ERROR_UNREF(bs->error);
1682
1872
  gpr_slice_buffer_destroy(&bs->slices);
1683
1873
  gpr_free(bs);
1684
1874
  }
@@ -1747,9 +1937,10 @@ static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx,
1747
1937
  }
1748
1938
  if (bs->slices.count > 0) {
1749
1939
  *arg->slice = gpr_slice_buffer_take_first(&bs->slices);
1750
- grpc_exec_ctx_enqueue(exec_ctx, arg->on_complete, true, NULL);
1751
- } else if (bs->failed) {
1752
- grpc_exec_ctx_enqueue(exec_ctx, arg->on_complete, false, NULL);
1940
+ grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_NONE, NULL);
1941
+ } else if (bs->error != GRPC_ERROR_NONE) {
1942
+ grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_REF(bs->error),
1943
+ NULL);
1753
1944
  } else {
1754
1945
  bs->on_next = arg->on_complete;
1755
1946
  bs->next = arg->slice;
@@ -1806,7 +1997,7 @@ static void incoming_byte_stream_push_locked(grpc_exec_ctx *exec_ctx,
1806
1997
  grpc_chttp2_incoming_byte_stream *bs = arg->byte_stream;
1807
1998
  if (bs->on_next != NULL) {
1808
1999
  *bs->next = arg->slice;
1809
- grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, true, NULL);
2000
+ grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE, NULL);
1810
2001
  bs->on_next = NULL;
1811
2002
  } else {
1812
2003
  gpr_slice_buffer_add(&bs->slices, arg->slice);
@@ -1824,13 +2015,30 @@ void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
1824
2015
  sizeof(arg));
1825
2016
  }
1826
2017
 
2018
+ typedef struct {
2019
+ grpc_chttp2_incoming_byte_stream *bs;
2020
+ grpc_error *error;
2021
+ } bs_fail_args;
2022
+
2023
+ static bs_fail_args *make_bs_fail_args(grpc_chttp2_incoming_byte_stream *bs,
2024
+ grpc_error *error) {
2025
+ bs_fail_args *a = gpr_malloc(sizeof(*a));
2026
+ a->bs = bs;
2027
+ a->error = error;
2028
+ return a;
2029
+ }
2030
+
1827
2031
  static void incoming_byte_stream_finished_failed_locked(
1828
2032
  grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
1829
2033
  void *argp) {
1830
- grpc_chttp2_incoming_byte_stream *bs = argp;
1831
- grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, false, NULL);
2034
+ bs_fail_args *a = argp;
2035
+ grpc_chttp2_incoming_byte_stream *bs = a->bs;
2036
+ grpc_error *error = a->error;
2037
+ gpr_free(a);
2038
+ grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL);
1832
2039
  bs->on_next = NULL;
1833
- bs->failed = 1;
2040
+ GRPC_ERROR_UNREF(bs->error);
2041
+ bs->error = error;
1834
2042
  incoming_byte_stream_unref(exec_ctx, bs);
1835
2043
  }
1836
2044
 
@@ -1843,25 +2051,26 @@ static void incoming_byte_stream_finished_ok_locked(grpc_exec_ctx *exec_ctx,
1843
2051
  }
1844
2052
 
1845
2053
  void grpc_chttp2_incoming_byte_stream_finished(
1846
- grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
1847
- int from_parsing_thread) {
2054
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
2055
+ grpc_error *error, int from_parsing_thread) {
1848
2056
  if (from_parsing_thread) {
1849
- if (success) {
2057
+ if (error == GRPC_ERROR_NONE) {
1850
2058
  grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream,
1851
2059
  incoming_byte_stream_finished_ok_locked,
1852
2060
  bs, 0);
1853
2061
  } else {
1854
- incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport,
1855
- bs->stream, bs);
1856
- }
1857
- } else {
1858
- if (success) {
1859
2062
  grpc_chttp2_run_with_global_lock(
1860
2063
  exec_ctx, bs->transport, bs->stream,
1861
- incoming_byte_stream_finished_failed_locked, bs, 0);
2064
+ incoming_byte_stream_finished_failed_locked,
2065
+ make_bs_fail_args(bs, error), 0);
2066
+ }
2067
+ } else {
2068
+ if (error == GRPC_ERROR_NONE) {
2069
+ incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport,
2070
+ bs->stream, bs);
1862
2071
  } else {
1863
- incoming_byte_stream_finished_failed_locked(exec_ctx, bs->transport,
1864
- bs->stream, bs);
2072
+ incoming_byte_stream_finished_failed_locked(
2073
+ exec_ctx, bs->transport, bs->stream, make_bs_fail_args(bs, error));
1865
2074
  }
1866
2075
  }
1867
2076
  }
@@ -1884,7 +2093,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
1884
2093
  gpr_slice_buffer_init(&incoming_byte_stream->slices);
1885
2094
  incoming_byte_stream->on_next = NULL;
1886
2095
  incoming_byte_stream->is_tail = 1;
1887
- incoming_byte_stream->failed = 0;
2096
+ incoming_byte_stream->error = GRPC_ERROR_NONE;
1888
2097
  if (add_to_queue->head == NULL) {
1889
2098
  add_to_queue->head = incoming_byte_stream;
1890
2099
  } else {
@@ -1903,10 +2112,13 @@ static char *format_flowctl_context_var(const char *context, const char *var,
1903
2112
  int64_t val, uint32_t id,
1904
2113
  char **scope) {
1905
2114
  char *underscore_pos;
2115
+ char *buf;
1906
2116
  char *result;
1907
2117
  if (context == NULL) {
1908
2118
  *scope = NULL;
1909
- gpr_asprintf(&result, "%s(%lld)", var, val);
2119
+ gpr_asprintf(&buf, "%s(%" PRId64 ")", var, val);
2120
+ result = gpr_leftpad(buf, ' ', 40);
2121
+ gpr_free(buf);
1910
2122
  return result;
1911
2123
  }
1912
2124
  underscore_pos = strchr(context, '_');
@@ -1917,7 +2129,9 @@ static char *format_flowctl_context_var(const char *context, const char *var,
1917
2129
  gpr_asprintf(scope, "%s[%d]", tmp, id);
1918
2130
  gpr_free(tmp);
1919
2131
  }
1920
- gpr_asprintf(&result, "%s.%s(%lld)", underscore_pos + 1, var, val);
2132
+ gpr_asprintf(&buf, "%s.%s(%" PRId64 ")", underscore_pos + 1, var, val);
2133
+ result = gpr_leftpad(buf, ' ', 40);
2134
+ gpr_free(buf);
1921
2135
  return result;
1922
2136
  }
1923
2137
 
@@ -1938,6 +2152,8 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
1938
2152
  uint32_t stream_id, int64_t val1, int64_t val2) {
1939
2153
  char *scope1;
1940
2154
  char *scope2;
2155
+ char *tmp_phase;
2156
+ char *tmp_scope1;
1941
2157
  char *label1 =
1942
2158
  format_flowctl_context_var(context1, var1, val1, stream_id, &scope1);
1943
2159
  char *label2 =
@@ -1945,14 +2161,18 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
1945
2161
  char *clisvr = is_client ? "client" : "server";
1946
2162
  char *prefix;
1947
2163
 
1948
- gpr_asprintf(&prefix, "FLOW % 8s: %s % 11s ", phase, clisvr, scope1);
2164
+ tmp_phase = gpr_leftpad(phase, ' ', 8);
2165
+ tmp_scope1 = gpr_leftpad(scope1, ' ', 11);
2166
+ gpr_asprintf(&prefix, "FLOW %s: %s %s ", phase, clisvr, scope1);
2167
+ gpr_free(tmp_phase);
2168
+ gpr_free(tmp_scope1);
1949
2169
 
1950
2170
  switch (op) {
1951
2171
  case GRPC_CHTTP2_FLOWCTL_MOVE:
1952
2172
  GPR_ASSERT(samestr(scope1, scope2));
1953
2173
  if (val2 != 0) {
1954
2174
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1955
- "%sMOVE % 40s <- % 40s giving %d", prefix, label1, label2,
2175
+ "%sMOVE %s <- %s giving %" PRId64, prefix, label1, label2,
1956
2176
  val1 + val2);
1957
2177
  }
1958
2178
  break;
@@ -1960,7 +2180,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
1960
2180
  GPR_ASSERT(val2 >= 0);
1961
2181
  if (val2 != 0) {
1962
2182
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1963
- "%sCREDIT % 40s by % 40s giving %d", prefix, label1, label2,
2183
+ "%sCREDIT %s by %s giving %" PRId64, prefix, label1, label2,
1964
2184
  val1 + val2);
1965
2185
  }
1966
2186
  break;
@@ -1968,7 +2188,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
1968
2188
  GPR_ASSERT(val2 >= 0);
1969
2189
  if (val2 != 0) {
1970
2190
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1971
- "%sDEBIT % 40s by % 40s giving %d", prefix, label1, label2,
2191
+ "%sDEBIT %s by %s giving %" PRId64, prefix, label1, label2,
1972
2192
  val1 - val2);
1973
2193
  }
1974
2194
  break;
@@ -1993,6 +2213,7 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
1993
2213
  "chttp2",
1994
2214
  init_stream,
1995
2215
  set_pollset,
2216
+ set_pollset_set,
1996
2217
  perform_stream_op,
1997
2218
  perform_transport_op,
1998
2219
  destroy_stream,
@@ -2013,5 +2234,5 @@ void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
2013
2234
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
2014
2235
  REF_TRANSPORT(t, "reading_action"); /* matches unref inside reading_action */
2015
2236
  gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
2016
- reading_action(exec_ctx, t, 1);
2237
+ reading_action(exec_ctx, t, GRPC_ERROR_NONE);
2017
2238
  }