grpc 1.23.1 → 1.24.0.pre1

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 (245) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +757 -477
  3. data/include/grpc/grpc.h +3 -1
  4. data/include/grpc/grpc_security.h +20 -4
  5. data/include/grpc/impl/codegen/grpc_types.h +6 -5
  6. data/include/grpc/impl/codegen/port_platform.h +25 -0
  7. data/src/core/ext/filters/client_channel/backend_metric.cc +78 -0
  8. data/src/core/ext/filters/client_channel/backend_metric.h +36 -0
  9. data/src/core/ext/filters/client_channel/channel_connectivity.cc +16 -2
  10. data/src/core/ext/filters/client_channel/client_channel.cc +325 -267
  11. data/src/core/ext/filters/client_channel/client_channel_factory.h +0 -4
  12. data/src/core/ext/filters/client_channel/health/health_check_client.cc +23 -32
  13. data/src/core/ext/filters/client_channel/http_proxy.cc +7 -3
  14. data/src/core/ext/filters/client_channel/lb_policy.cc +1 -1
  15. data/src/core/ext/filters/client_channel/lb_policy.h +58 -34
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +46 -50
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +9 -2
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +35 -17
  19. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +130 -215
  20. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +34 -21
  21. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +1120 -802
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h +8 -2
  23. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc +33 -12
  24. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.cc +151 -40
  25. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h +184 -26
  26. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +389 -245
  27. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h +98 -60
  28. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +6 -1
  29. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +89 -0
  30. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +3 -8
  31. data/src/core/ext/filters/client_channel/server_address.cc +1 -3
  32. data/src/core/ext/filters/client_channel/server_address.h +1 -1
  33. data/src/core/ext/filters/client_channel/subchannel.h +2 -1
  34. data/src/core/ext/filters/client_idle/client_idle_filter.cc +207 -29
  35. data/src/core/ext/filters/http/client/http_client_filter.cc +10 -8
  36. data/src/core/ext/filters/http/client_authority_filter.cc +1 -1
  37. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +10 -7
  38. data/src/core/ext/filters/http/server/http_server_filter.cc +52 -26
  39. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +23 -20
  40. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +24 -21
  41. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +1 -1
  42. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +37 -24
  43. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +1 -0
  44. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +237 -191
  45. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +29 -27
  46. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +1 -1
  47. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +19 -4
  48. data/src/core/ext/transport/chttp2/transport/hpack_table.h +13 -4
  49. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +2 -1
  50. data/src/core/ext/transport/chttp2/transport/internal.h +0 -2
  51. data/src/core/ext/transport/chttp2/transport/parsing.cc +99 -71
  52. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c +222 -0
  53. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h +818 -0
  54. data/src/core/ext/upb-generated/envoy/api/v2/cds.upb.c +314 -0
  55. data/src/core/ext/upb-generated/envoy/api/v2/cds.upb.h +1142 -0
  56. data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c +53 -0
  57. data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h +158 -0
  58. data/src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c +34 -0
  59. data/src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h +69 -0
  60. data/src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c +49 -0
  61. data/src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h +240 -0
  62. data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c +110 -0
  63. data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h +324 -0
  64. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c +235 -0
  65. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h +661 -0
  66. data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c +84 -0
  67. data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h +274 -0
  68. data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c +175 -0
  69. data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h +572 -0
  70. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c +150 -0
  71. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h +596 -0
  72. data/src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c +35 -0
  73. data/src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h +80 -0
  74. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c +95 -0
  75. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h +308 -0
  76. data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c +128 -0
  77. data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h +392 -0
  78. data/src/core/ext/upb-generated/envoy/api/v2/eds.upb.c +91 -0
  79. data/src/core/ext/upb-generated/envoy/api/v2/eds.upb.h +236 -0
  80. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c +88 -0
  81. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h +258 -0
  82. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c +111 -0
  83. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h +324 -0
  84. data/src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c +23 -0
  85. data/src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h +50 -0
  86. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c +52 -0
  87. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h +130 -0
  88. data/src/core/ext/upb-generated/envoy/type/percent.upb.c +39 -0
  89. data/src/core/ext/upb-generated/envoy/type/percent.upb.h +87 -0
  90. data/src/core/ext/upb-generated/envoy/type/range.upb.c +39 -0
  91. data/src/core/ext/upb-generated/envoy/type/range.upb.h +85 -0
  92. data/src/core/ext/upb-generated/gogoproto/gogo.upb.c +17 -0
  93. data/src/core/ext/upb-generated/gogoproto/gogo.upb.h +30 -0
  94. data/src/core/ext/upb-generated/google/api/annotations.upb.c +18 -0
  95. data/src/core/ext/upb-generated/google/api/annotations.upb.h +30 -0
  96. data/src/core/ext/upb-generated/google/api/http.upb.c +66 -0
  97. data/src/core/ext/upb-generated/google/api/http.upb.h +190 -0
  98. data/src/core/ext/upb-generated/google/protobuf/any.upb.c +27 -0
  99. data/src/core/ext/upb-generated/google/protobuf/any.upb.h +58 -0
  100. data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.c +485 -0
  101. data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.h +1690 -0
  102. data/src/core/ext/upb-generated/google/protobuf/duration.upb.c +27 -0
  103. data/src/core/ext/upb-generated/google/protobuf/duration.upb.h +58 -0
  104. data/src/core/ext/upb-generated/google/protobuf/empty.upb.c +22 -0
  105. data/src/core/ext/upb-generated/google/protobuf/empty.upb.h +50 -0
  106. data/src/core/ext/upb-generated/google/protobuf/struct.upb.c +79 -0
  107. data/src/core/ext/upb-generated/google/protobuf/struct.upb.h +215 -0
  108. data/src/core/ext/upb-generated/google/protobuf/timestamp.upb.c +27 -0
  109. data/src/core/ext/upb-generated/google/protobuf/timestamp.upb.h +58 -0
  110. data/src/core/ext/upb-generated/google/protobuf/wrappers.upb.c +106 -0
  111. data/src/core/ext/upb-generated/google/protobuf/wrappers.upb.h +238 -0
  112. data/src/core/ext/upb-generated/google/rpc/status.upb.c +33 -0
  113. data/src/core/ext/upb-generated/google/rpc/status.upb.h +74 -0
  114. data/src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c +49 -0
  115. data/src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h +126 -0
  116. data/src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c +209 -0
  117. data/src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h +681 -0
  118. data/src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c +42 -0
  119. data/src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h +109 -0
  120. data/src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c +36 -0
  121. data/src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h +84 -0
  122. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c +133 -0
  123. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h +359 -0
  124. data/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c +58 -0
  125. data/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h +144 -0
  126. data/src/core/ext/upb-generated/validate/validate.upb.c +443 -0
  127. data/src/core/ext/upb-generated/validate/validate.upb.h +2037 -0
  128. data/src/core/lib/channel/channel_args.cc +21 -0
  129. data/src/core/lib/channel/channel_args.h +16 -2
  130. data/src/core/lib/channel/channel_stack.h +2 -1
  131. data/src/core/lib/channel/channelz.cc +54 -56
  132. data/src/core/lib/channel/channelz.h +29 -12
  133. data/src/core/lib/compression/compression.cc +2 -1
  134. data/src/core/lib/compression/compression_internal.h +8 -0
  135. data/src/core/lib/gpr/log_linux.cc +2 -2
  136. data/src/core/lib/gpr/log_posix.cc +2 -2
  137. data/src/core/lib/gpr/time_precise.cc +123 -36
  138. data/src/core/lib/gpr/time_precise.h +37 -0
  139. data/src/core/lib/gprpp/abstract.h +10 -0
  140. data/src/core/lib/gprpp/atomic.h +4 -0
  141. data/src/core/lib/gprpp/inlined_vector.h +20 -4
  142. data/src/core/lib/gprpp/map.h +109 -6
  143. data/src/core/lib/gprpp/memory.h +6 -0
  144. data/src/core/lib/gprpp/ref_counted_ptr.h +2 -0
  145. data/src/core/lib/iomgr/ev_epollex_linux.cc +29 -54
  146. data/src/core/lib/iomgr/exec_ctx.cc +27 -17
  147. data/src/core/lib/iomgr/exec_ctx.h +3 -0
  148. data/src/core/lib/iomgr/sockaddr_utils.cc +1 -3
  149. data/src/core/lib/iomgr/tcp_posix.cc +16 -25
  150. data/src/core/lib/iomgr/tcp_server_custom.cc +1 -1
  151. data/src/core/lib/iomgr/timer_manager.cc +8 -1
  152. data/src/core/lib/iomgr/timer_manager.h +2 -0
  153. data/src/core/lib/security/credentials/credentials.h +8 -2
  154. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +23 -0
  155. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +3 -0
  156. data/src/core/lib/security/credentials/tls/spiffe_credentials.cc +3 -3
  157. data/src/core/lib/security/security_connector/ssl_utils.cc +1 -12
  158. data/src/core/lib/security/security_connector/ssl_utils.h +10 -6
  159. data/src/core/lib/security/security_connector/ssl_utils_config.cc +32 -0
  160. data/src/core/lib/security/security_connector/ssl_utils_config.h +30 -0
  161. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +161 -49
  162. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +34 -1
  163. data/src/core/lib/slice/slice_intern.cc +17 -9
  164. data/src/core/lib/slice/slice_internal.h +34 -7
  165. data/src/core/lib/slice/slice_utils.h +7 -3
  166. data/src/core/lib/surface/call.cc +97 -57
  167. data/src/core/lib/surface/channel.cc +2 -2
  168. data/src/core/lib/surface/completion_queue.cc +10 -16
  169. data/src/core/lib/surface/init.cc +3 -0
  170. data/src/core/lib/surface/server.cc +11 -14
  171. data/src/core/lib/surface/validate_metadata.cc +4 -0
  172. data/src/core/lib/surface/version.cc +2 -2
  173. data/src/core/lib/transport/metadata.cc +4 -4
  174. data/src/core/lib/transport/metadata_batch.cc +72 -16
  175. data/src/core/lib/transport/metadata_batch.h +38 -0
  176. data/src/core/lib/transport/static_metadata.cc +814 -1023
  177. data/src/core/lib/transport/static_metadata.h +271 -213
  178. data/src/core/lib/transport/transport.h +12 -0
  179. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -0
  180. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +104 -76
  181. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +34 -16
  182. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +2 -2
  183. data/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +10 -6
  184. data/src/core/tsi/alts/handshaker/alts_tsi_utils.h +4 -3
  185. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +74 -48
  186. data/src/core/tsi/alts/handshaker/transport_security_common_api.h +34 -26
  187. data/src/core/tsi/ssl_transport_security.cc +14 -6
  188. data/src/core/tsi/ssl_transport_security.h +4 -0
  189. data/src/ruby/ext/grpc/ext-export.clang +1 -0
  190. data/src/ruby/ext/grpc/ext-export.gcc +6 -0
  191. data/src/ruby/ext/grpc/extconf.rb +5 -0
  192. data/src/ruby/ext/grpc/rb_enable_cpp.cc +22 -0
  193. data/src/ruby/ext/grpc/rb_grpc.c +1 -42
  194. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -0
  195. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +6 -0
  196. data/src/ruby/lib/grpc.rb +2 -0
  197. data/src/ruby/lib/grpc/core/status_codes.rb +135 -0
  198. data/src/ruby/lib/grpc/errors.rb +4 -7
  199. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +9 -4
  200. data/src/ruby/lib/grpc/structs.rb +15 -0
  201. data/src/ruby/lib/grpc/version.rb +1 -1
  202. data/src/ruby/spec/errors_spec.rb +1 -0
  203. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import.proto +22 -0
  204. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +34 -0
  205. data/src/ruby/spec/pb/codegen/package_option_spec.rb +53 -29
  206. data/third_party/upb/upb/decode.c +604 -0
  207. data/third_party/upb/upb/decode.h +21 -0
  208. data/third_party/upb/upb/encode.c +378 -0
  209. data/third_party/upb/upb/encode.h +21 -0
  210. data/third_party/upb/upb/generated_util.h +105 -0
  211. data/third_party/upb/upb/msg.c +111 -0
  212. data/third_party/upb/upb/msg.h +69 -0
  213. data/third_party/upb/upb/port.c +27 -0
  214. data/third_party/upb/upb/port_def.inc +152 -0
  215. data/third_party/upb/upb/port_undef.inc +21 -0
  216. data/third_party/upb/upb/table.c +911 -0
  217. data/third_party/upb/upb/table.int.h +507 -0
  218. data/third_party/upb/upb/upb.c +261 -0
  219. data/third_party/upb/upb/upb.h +364 -0
  220. metadata +134 -55
  221. data/src/core/ext/filters/client_channel/health/health.pb.c +0 -23
  222. data/src/core/ext/filters/client_channel/health/health.pb.h +0 -73
  223. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c +0 -19
  224. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h +0 -54
  225. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c +0 -19
  226. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h +0 -54
  227. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +0 -89
  228. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +0 -164
  229. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc +0 -520
  230. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api.h +0 -323
  231. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc +0 -145
  232. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h +0 -149
  233. data/src/core/tsi/alts/handshaker/altscontext.pb.c +0 -47
  234. data/src/core/tsi/alts/handshaker/altscontext.pb.h +0 -63
  235. data/src/core/tsi/alts/handshaker/handshaker.pb.c +0 -122
  236. data/src/core/tsi/alts/handshaker/handshaker.pb.h +0 -254
  237. data/src/core/tsi/alts/handshaker/transport_security_common.pb.c +0 -49
  238. data/src/core/tsi/alts/handshaker/transport_security_common.pb.h +0 -78
  239. data/third_party/nanopb/pb.h +0 -579
  240. data/third_party/nanopb/pb_common.c +0 -97
  241. data/third_party/nanopb/pb_common.h +0 -42
  242. data/third_party/nanopb/pb_decode.c +0 -1347
  243. data/third_party/nanopb/pb_decode.h +0 -149
  244. data/third_party/nanopb/pb_encode.c +0 -696
  245. data/third_party/nanopb/pb_encode.h +0 -154
@@ -29,6 +29,7 @@
29
29
  extern grpc_core::TraceFlag grpc_http_trace;
30
30
  extern grpc_core::TraceFlag grpc_trace_http2_stream_state;
31
31
  extern grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount;
32
+ extern grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_hpack_parser;
32
33
 
33
34
  extern bool g_flow_control_enabled;
34
35
 
@@ -88,7 +88,19 @@ typedef struct {
88
88
  * with a data frame header */
89
89
  static void fill_header(uint8_t* p, uint8_t type, uint32_t id, size_t len,
90
90
  uint8_t flags) {
91
- GPR_ASSERT(len < 16777316);
91
+ /* len is the current frame size (i.e. for the frame we're finishing).
92
+ We finish a frame if:
93
+ 1) We called ensure_space(), (i.e. add_tiny_header_data()) and adding
94
+ 'need_bytes' to the frame would cause us to exceed st->max_frame_size.
95
+ 2) We called add_header_data, and adding the slice would cause us to exceed
96
+ st->max_frame_size.
97
+ 3) We're done encoding the header.
98
+
99
+ Thus, len is always <= st->max_frame_size.
100
+ st->max_frame_size is derived from GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
101
+ which has a max allowable value of 16777215 (see chttp_transport.cc).
102
+ Thus, the following assert can be a debug assert. */
103
+ GPR_DEBUG_ASSERT(len < 16777316);
92
104
  *p++ = static_cast<uint8_t>(len >> 16);
93
105
  *p++ = static_cast<uint8_t>(len >> 8);
94
106
  *p++ = static_cast<uint8_t>(len);
@@ -100,6 +112,13 @@ static void fill_header(uint8_t* p, uint8_t type, uint32_t id, size_t len,
100
112
  *p++ = static_cast<uint8_t>(id);
101
113
  }
102
114
 
115
+ static size_t current_frame_size(framer_state* st) {
116
+ const size_t frame_size =
117
+ st->output->length - st->output_length_at_start_of_frame;
118
+ GPR_DEBUG_ASSERT(frame_size <= st->max_frame_size);
119
+ return frame_size;
120
+ }
121
+
103
122
  /* finish a frame - fill in the previously reserved header */
104
123
  static void finish_frame(framer_state* st, int is_header_boundary,
105
124
  int is_last_in_stream) {
@@ -108,7 +127,7 @@ static void finish_frame(framer_state* st, int is_header_boundary,
108
127
  : GRPC_CHTTP2_FRAME_CONTINUATION;
109
128
  fill_header(
110
129
  GRPC_SLICE_START_PTR(st->output->slices[st->header_idx]), type,
111
- st->stream_id, st->output->length - st->output_length_at_start_of_frame,
130
+ st->stream_id, current_frame_size(st),
112
131
  static_cast<uint8_t>(
113
132
  (is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) |
114
133
  (is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0)));
@@ -130,9 +149,7 @@ static void begin_frame(framer_state* st) {
130
149
  space to add at least about_to_add bytes -- finishes the current frame if
131
150
  needed */
132
151
  static void ensure_space(framer_state* st, size_t need_bytes) {
133
- if (GPR_LIKELY(st->output->length - st->output_length_at_start_of_frame +
134
- need_bytes <=
135
- st->max_frame_size)) {
152
+ if (GPR_LIKELY(current_frame_size(st) + need_bytes <= st->max_frame_size)) {
136
153
  return;
137
154
  }
138
155
  finish_frame(st, 0, 0);
@@ -158,8 +175,7 @@ static void add_header_data(framer_state* st, grpc_slice slice) {
158
175
  size_t len = GRPC_SLICE_LENGTH(slice);
159
176
  size_t remaining;
160
177
  if (len == 0) return;
161
- remaining = st->max_frame_size + st->output_length_at_start_of_frame -
162
- st->output->length;
178
+ remaining = st->max_frame_size - current_frame_size(st);
163
179
  if (len <= remaining) {
164
180
  st->stats->header_bytes += len;
165
181
  grpc_slice_buffer_add(st->output, slice);
@@ -325,132 +341,129 @@ static void emit_indexed(grpc_chttp2_hpack_compressor* c, uint32_t elem_index,
325
341
  len);
326
342
  }
327
343
 
328
- typedef struct {
329
- grpc_slice data;
330
- uint8_t huffman_prefix;
331
- bool insert_null_before_wire_value;
332
- } wire_value;
344
+ struct wire_value {
345
+ wire_value(uint8_t huffman_prefix, bool insert_null_before_wire_value,
346
+ const grpc_slice& slice)
347
+ : data(slice),
348
+ huffman_prefix(huffman_prefix),
349
+ insert_null_before_wire_value(insert_null_before_wire_value),
350
+ length(GRPC_SLICE_LENGTH(slice) +
351
+ (insert_null_before_wire_value ? 1 : 0)) {}
352
+ // While wire_value is const from the POV of hpack encoder code, actually
353
+ // adding it to a slice buffer will possibly split the slice.
354
+ const grpc_slice data;
355
+ const uint8_t huffman_prefix;
356
+ const bool insert_null_before_wire_value;
357
+ const size_t length;
358
+ };
333
359
 
334
360
  template <bool mdkey_definitely_interned>
335
361
  static wire_value get_wire_value(grpc_mdelem elem, bool true_binary_enabled) {
336
- wire_value wire_val;
337
- bool is_bin_hdr =
362
+ const bool is_bin_hdr =
338
363
  mdkey_definitely_interned
339
364
  ? grpc_is_refcounted_slice_binary_header(GRPC_MDKEY(elem))
340
365
  : grpc_is_binary_header_internal(GRPC_MDKEY(elem));
366
+ const grpc_slice& value = GRPC_MDVALUE(elem);
341
367
  if (is_bin_hdr) {
342
368
  if (true_binary_enabled) {
343
369
  GRPC_STATS_INC_HPACK_SEND_BINARY();
344
- wire_val.huffman_prefix = 0x00;
345
- wire_val.insert_null_before_wire_value = true;
346
- wire_val.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem));
347
-
370
+ return wire_value(0x00, true, grpc_slice_ref_internal(value));
348
371
  } else {
349
372
  GRPC_STATS_INC_HPACK_SEND_BINARY_BASE64();
350
- wire_val.huffman_prefix = 0x80;
351
- wire_val.insert_null_before_wire_value = false;
352
- wire_val.data =
353
- grpc_chttp2_base64_encode_and_huffman_compress(GRPC_MDVALUE(elem));
373
+ return wire_value(0x80, false,
374
+ grpc_chttp2_base64_encode_and_huffman_compress(value));
354
375
  }
355
376
  } else {
356
377
  /* TODO(ctiller): opportunistically compress non-binary headers */
357
378
  GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
358
- wire_val.huffman_prefix = 0x00;
359
- wire_val.insert_null_before_wire_value = false;
360
- wire_val.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem));
379
+ return wire_value(0x00, false, grpc_slice_ref_internal(value));
361
380
  }
362
- return wire_val;
363
- }
364
-
365
- static size_t wire_value_length(wire_value v) {
366
- return GPR_SLICE_LENGTH(v.data) + v.insert_null_before_wire_value;
367
381
  }
368
382
 
369
- static void add_wire_value(framer_state* st, wire_value v) {
370
- if (v.insert_null_before_wire_value) *add_tiny_header_data(st, 1) = 0;
371
- add_header_data(st, v.data);
383
+ static uint32_t wire_value_length(const wire_value& v) {
384
+ GPR_DEBUG_ASSERT(v.length <= UINT32_MAX);
385
+ return static_cast<uint32_t>(v.length);
372
386
  }
373
387
 
374
- static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor* c,
375
- uint32_t key_index, grpc_mdelem elem,
376
- framer_state* st) {
377
- GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX();
378
- uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
379
- wire_value value = get_wire_value<true>(elem, st->use_true_binary_metadata);
380
- size_t len_val = wire_value_length(value);
381
- uint32_t len_val_len;
382
- GPR_ASSERT(len_val <= UINT32_MAX);
383
- len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
384
- GPR_DEBUG_ASSERT(len_pfx + len_val_len < GRPC_SLICE_INLINED_SIZE);
385
- uint8_t* data = add_tiny_header_data(st, len_pfx + len_val_len);
386
- GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40, data, len_pfx);
387
- GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix,
388
- &data[len_pfx], len_val_len);
389
- add_wire_value(st, value);
390
- }
391
-
392
- static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor* c,
393
- uint32_t key_index, grpc_mdelem elem,
394
- framer_state* st) {
395
- GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX();
396
- uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
397
- wire_value value = get_wire_value<false>(elem, st->use_true_binary_metadata);
398
- size_t len_val = wire_value_length(value);
399
- uint32_t len_val_len;
400
- GPR_ASSERT(len_val <= UINT32_MAX);
401
- len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
388
+ namespace {
389
+ enum class EmitLitHdrType { INC_IDX, NO_IDX };
390
+
391
+ enum class EmitLitHdrVType { INC_IDX_V, NO_IDX_V };
392
+ } // namespace
393
+
394
+ template <EmitLitHdrType type>
395
+ static void emit_lithdr(grpc_chttp2_hpack_compressor* c, uint32_t key_index,
396
+ grpc_mdelem elem, framer_state* st) {
397
+ switch (type) {
398
+ case EmitLitHdrType::INC_IDX:
399
+ GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX();
400
+ break;
401
+ case EmitLitHdrType::NO_IDX:
402
+ GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX();
403
+ break;
404
+ }
405
+ const uint32_t len_pfx = type == EmitLitHdrType::INC_IDX
406
+ ? GRPC_CHTTP2_VARINT_LENGTH(key_index, 2)
407
+ : GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
408
+ const wire_value value =
409
+ get_wire_value<true>(elem, st->use_true_binary_metadata);
410
+ const uint32_t len_val = wire_value_length(value);
411
+ const uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
402
412
  GPR_DEBUG_ASSERT(len_pfx + len_val_len < GRPC_SLICE_INLINED_SIZE);
403
- uint8_t* data = add_tiny_header_data(st, len_pfx + len_val_len);
404
- GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00, data, len_pfx);
405
- GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix,
406
- &data[len_pfx], len_val_len);
407
- add_wire_value(st, value);
408
- }
409
-
410
- static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor* c,
411
- uint32_t unused_index, grpc_mdelem elem,
412
- framer_state* st) {
413
- GPR_ASSERT(unused_index == 0);
414
- GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V();
415
- GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
416
- uint32_t len_key = static_cast<uint32_t> GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
417
- wire_value value = get_wire_value<true>(elem, st->use_true_binary_metadata);
418
- uint32_t len_val = static_cast<uint32_t>(wire_value_length(value));
419
- uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
420
- uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
421
- GPR_ASSERT(len_key <= UINT32_MAX);
422
- GPR_ASSERT(wire_value_length(value) <= UINT32_MAX);
423
- GPR_DEBUG_ASSERT(1 + len_key_len < GRPC_SLICE_INLINED_SIZE);
424
- uint8_t* data = add_tiny_header_data(st, 1 + len_key_len);
425
- data[0] = 0x40;
426
- GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, &data[1], len_key_len);
427
- add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
428
- GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix,
429
- add_tiny_header_data(st, len_val_len), len_val_len);
430
- add_wire_value(st, value);
413
+ uint8_t* data = add_tiny_header_data(
414
+ st,
415
+ len_pfx + len_val_len + (value.insert_null_before_wire_value ? 1 : 0));
416
+ switch (type) {
417
+ case EmitLitHdrType::INC_IDX:
418
+ GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40, data, len_pfx);
419
+ break;
420
+ case EmitLitHdrType::NO_IDX:
421
+ GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00, data, len_pfx);
422
+ break;
423
+ }
424
+ GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix, &data[len_pfx],
425
+ len_val_len);
426
+ if (value.insert_null_before_wire_value) {
427
+ data[len_pfx + len_val_len] = 0;
428
+ }
429
+ add_header_data(st, value.data);
431
430
  }
432
431
 
433
- static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor* c,
434
- uint32_t unused_index, grpc_mdelem elem,
435
- framer_state* st) {
436
- GPR_ASSERT(unused_index == 0);
437
- GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V();
432
+ template <EmitLitHdrVType type>
433
+ static void emit_lithdr_v(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
434
+ framer_state* st) {
435
+ switch (type) {
436
+ case EmitLitHdrVType::INC_IDX_V:
437
+ GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V();
438
+ break;
439
+ case EmitLitHdrVType::NO_IDX_V:
440
+ GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V();
441
+ break;
442
+ }
438
443
  GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
439
- uint32_t len_key = static_cast<uint32_t> GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
440
- wire_value value = get_wire_value<false>(elem, st->use_true_binary_metadata);
441
- uint32_t len_val = static_cast<uint32_t>(wire_value_length(value));
442
- uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
443
- uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
444
- GPR_ASSERT(len_key <= UINT32_MAX);
445
- GPR_ASSERT(wire_value_length(value) <= UINT32_MAX);
446
- /* Preconditions passed; emit header. */
447
- uint8_t* data = add_tiny_header_data(st, 1 + len_key_len);
448
- data[0] = 0x00;
449
- GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, &data[1], len_key_len);
444
+ const uint32_t len_key =
445
+ static_cast<uint32_t>(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)));
446
+ const wire_value value =
447
+ type == EmitLitHdrVType::INC_IDX_V
448
+ ? get_wire_value<true>(elem, st->use_true_binary_metadata)
449
+ : get_wire_value<false>(elem, st->use_true_binary_metadata);
450
+ const uint32_t len_val = wire_value_length(value);
451
+ const uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
452
+ const uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
453
+ GPR_DEBUG_ASSERT(len_key <= UINT32_MAX);
454
+ GPR_DEBUG_ASSERT(1 + len_key_len < GRPC_SLICE_INLINED_SIZE);
455
+ uint8_t* key_buf = add_tiny_header_data(st, 1 + len_key_len);
456
+ key_buf[0] = type == EmitLitHdrVType::INC_IDX_V ? 0x40 : 0x00;
457
+ GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, &key_buf[1], len_key_len);
450
458
  add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
451
- GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix,
452
- add_tiny_header_data(st, len_val_len), len_val_len);
453
- add_wire_value(st, value);
459
+ uint8_t* value_buf = add_tiny_header_data(
460
+ st, len_val_len + (value.insert_null_before_wire_value ? 1 : 0));
461
+ GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix, value_buf,
462
+ len_val_len);
463
+ if (value.insert_null_before_wire_value) {
464
+ value_buf[len_val_len] = 0;
465
+ }
466
+ add_header_data(st, value.data);
454
467
  }
455
468
 
456
469
  static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor* c,
@@ -461,113 +474,142 @@ static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor* c,
461
474
  c->advertise_table_size_change = 0;
462
475
  }
463
476
 
477
+ static void GPR_ATTRIBUTE_NOINLINE hpack_enc_log(grpc_mdelem elem) {
478
+ char* k = grpc_slice_to_c_string(GRPC_MDKEY(elem));
479
+ char* v = nullptr;
480
+ if (grpc_is_binary_header_internal(GRPC_MDKEY(elem))) {
481
+ v = grpc_dump_slice(GRPC_MDVALUE(elem), GPR_DUMP_HEX);
482
+ } else {
483
+ v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
484
+ }
485
+ gpr_log(
486
+ GPR_INFO,
487
+ "Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
488
+ k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem),
489
+ grpc_slice_is_interned(GRPC_MDKEY(elem)),
490
+ grpc_slice_is_interned(GRPC_MDVALUE(elem)));
491
+ gpr_free(k);
492
+ gpr_free(v);
493
+ }
494
+
464
495
  static uint32_t dynidx(grpc_chttp2_hpack_compressor* c, uint32_t elem_index) {
465
496
  return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index +
466
497
  c->table_elems - elem_index;
467
498
  }
468
499
 
500
+ struct EmitIndexedStatus {
501
+ EmitIndexedStatus() = default;
502
+ EmitIndexedStatus(uint32_t elem_hash, bool emitted, bool can_add)
503
+ : elem_hash(elem_hash), emitted(emitted), can_add(can_add) {}
504
+ const uint32_t elem_hash = 0;
505
+ const bool emitted = false;
506
+ const bool can_add = false;
507
+ };
508
+
509
+ static EmitIndexedStatus maybe_emit_indexed(grpc_chttp2_hpack_compressor* c,
510
+ grpc_mdelem elem,
511
+ framer_state* st) {
512
+ const uint32_t elem_hash =
513
+ GRPC_MDELEM_STORAGE(elem) == GRPC_MDELEM_STORAGE_INTERNED
514
+ ? reinterpret_cast<grpc_core::InternedMetadata*>(
515
+ GRPC_MDELEM_DATA(elem))
516
+ ->hash()
517
+ : reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(elem))
518
+ ->hash();
519
+
520
+ inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems);
521
+
522
+ /* is this elem currently in the decoders table? */
523
+ if (grpc_mdelem_both_interned_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)],
524
+ elem) &&
525
+ c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
526
+ /* HIT: complete element (first cuckoo hash) */
527
+ emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
528
+ st);
529
+ return EmitIndexedStatus(elem_hash, true, false);
530
+ }
531
+ if (grpc_mdelem_both_interned_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)],
532
+ elem) &&
533
+ c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
534
+ /* HIT: complete element (second cuckoo hash) */
535
+ emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
536
+ st);
537
+ return EmitIndexedStatus(elem_hash, true, false);
538
+ }
539
+
540
+ const bool can_add = c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
541
+ c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
542
+ return EmitIndexedStatus(elem_hash, false, can_add);
543
+ }
544
+
545
+ static void emit_maybe_add(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
546
+ framer_state* st, uint32_t indices_key,
547
+ bool should_add_elem, size_t decoder_space_usage,
548
+ uint32_t elem_hash, uint32_t key_hash) {
549
+ if (should_add_elem) {
550
+ emit_lithdr<EmitLitHdrType::INC_IDX>(c, dynidx(c, indices_key), elem, st);
551
+ add_elem(c, elem, decoder_space_usage, elem_hash, key_hash);
552
+ } else {
553
+ emit_lithdr<EmitLitHdrType::NO_IDX>(c, dynidx(c, indices_key), elem, st);
554
+ }
555
+ }
556
+
469
557
  /* encode an mdelem */
470
558
  static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
471
559
  framer_state* st) {
472
- GPR_ASSERT(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)) > 0);
560
+ /* User-provided key len validated in grpc_validate_header_key_is_legal(). */
561
+ GPR_DEBUG_ASSERT(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)) > 0);
562
+ /* Header ordering: all reserved headers (prefixed with ':') must precede
563
+ * regular headers. This can be a debug assert, since:
564
+ * 1) User cannot give us ':' headers (grpc_validate_header_key_is_legal()).
565
+ * 2) grpc filters/core should be checked during debug builds. */
566
+ #ifndef NDEBUG
473
567
  if (GRPC_SLICE_START_PTR(GRPC_MDKEY(elem))[0] != ':') { /* regular header */
474
568
  st->seen_regular_header = 1;
475
569
  } else {
476
- GPR_ASSERT(
570
+ GPR_DEBUG_ASSERT(
477
571
  st->seen_regular_header == 0 &&
478
572
  "Reserved header (colon-prefixed) happening after regular ones.");
479
573
  }
480
-
574
+ #endif
481
575
  if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
482
- char* k = grpc_slice_to_c_string(GRPC_MDKEY(elem));
483
- char* v = nullptr;
484
- if (grpc_is_binary_header_internal(GRPC_MDKEY(elem))) {
485
- v = grpc_dump_slice(GRPC_MDVALUE(elem), GPR_DUMP_HEX);
486
- } else {
487
- v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
488
- }
489
- gpr_log(
490
- GPR_INFO,
491
- "Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
492
- k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem),
493
- grpc_slice_is_interned(GRPC_MDKEY(elem)),
494
- grpc_slice_is_interned(GRPC_MDVALUE(elem)));
495
- gpr_free(k);
496
- gpr_free(v);
576
+ hpack_enc_log(elem);
497
577
  }
498
578
 
499
- bool elem_interned = GRPC_MDELEM_IS_INTERNED(elem);
500
- bool key_interned = elem_interned || grpc_slice_is_interned(GRPC_MDKEY(elem));
579
+ const bool elem_interned = GRPC_MDELEM_IS_INTERNED(elem);
580
+ const bool key_interned =
581
+ elem_interned || grpc_slice_is_interned(GRPC_MDKEY(elem));
501
582
 
502
- // Key is not interned, emit literals.
583
+ /* Key is not interned, emit literals. */
503
584
  if (!key_interned) {
504
- emit_lithdr_noidx_v(c, 0, elem, st);
585
+ emit_lithdr_v<EmitLitHdrVType::NO_IDX_V>(c, elem, st);
505
586
  return;
506
587
  }
507
-
508
- uint32_t elem_hash = 0;
509
-
510
- if (elem_interned) {
511
- if (GRPC_MDELEM_STORAGE(elem) == GRPC_MDELEM_STORAGE_INTERNED) {
512
- elem_hash =
513
- reinterpret_cast<grpc_core::InternedMetadata*>(GRPC_MDELEM_DATA(elem))
514
- ->hash();
515
- } else {
516
- elem_hash =
517
- reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(elem))
518
- ->hash();
519
- }
520
-
521
- inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum,
522
- c->filter_elems);
523
-
524
- /* is this elem currently in the decoders table? */
525
- if (grpc_mdelem_both_interned_eq(
526
- c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) &&
527
- c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
528
- /* HIT: complete element (first cuckoo hash) */
529
- emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
530
- st);
531
- return;
532
- }
533
- if (grpc_mdelem_both_interned_eq(
534
- c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) &&
535
- c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
536
- /* HIT: complete element (second cuckoo hash) */
537
- emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
538
- st);
539
- return;
540
- }
588
+ /* Interned metadata => maybe already indexed. */
589
+ const EmitIndexedStatus ret =
590
+ elem_interned ? maybe_emit_indexed(c, elem, st) : EmitIndexedStatus();
591
+ if (ret.emitted) {
592
+ return;
541
593
  }
542
594
 
543
- uint32_t indices_key;
544
-
545
595
  /* should this elem be in the table? */
546
596
  const size_t decoder_space_usage =
547
597
  grpc_chttp2_get_size_in_hpack_table(elem, st->use_true_binary_metadata);
548
- const bool should_add_elem = elem_interned &&
549
- decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
550
- c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
551
- c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
552
-
553
- uint32_t key_hash = GRPC_MDKEY(elem).refcount->Hash(GRPC_MDKEY(elem));
554
- auto emit_maybe_add = [&should_add_elem, &elem, &st, &c, &indices_key,
555
- &decoder_space_usage, &elem_hash, &key_hash] {
556
- if (should_add_elem) {
557
- emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st);
558
- add_elem(c, elem, decoder_space_usage, elem_hash, key_hash);
559
- } else {
560
- emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
561
- }
562
- };
598
+ const bool decoder_space_available =
599
+ decoder_space_usage < MAX_DECODER_SPACE_USAGE;
600
+ const bool should_add_elem =
601
+ elem_interned && decoder_space_available && ret.can_add;
602
+ const uint32_t elem_hash = ret.elem_hash;
563
603
 
564
604
  /* no hits for the elem... maybe there's a key? */
565
- indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
605
+ const uint32_t key_hash = GRPC_MDKEY(elem).refcount->Hash(GRPC_MDKEY(elem));
606
+ uint32_t indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
566
607
  if (grpc_slice_static_interned_equal(
567
608
  c->entries_keys[HASH_FRAGMENT_2(key_hash)], GRPC_MDKEY(elem)) &&
568
609
  indices_key > c->tail_remote_index) {
569
610
  /* HIT: key (first cuckoo hash) */
570
- emit_maybe_add();
611
+ emit_maybe_add(c, elem, st, indices_key, should_add_elem,
612
+ decoder_space_usage, elem_hash, key_hash);
571
613
  return;
572
614
  }
573
615
 
@@ -575,18 +617,18 @@ static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
575
617
  if (grpc_slice_static_interned_equal(
576
618
  c->entries_keys[HASH_FRAGMENT_3(key_hash)], GRPC_MDKEY(elem)) &&
577
619
  indices_key > c->tail_remote_index) {
578
- /* HIT: key (first cuckoo hash) */
579
- emit_maybe_add();
620
+ /* HIT: key (second cuckoo hash) */
621
+ emit_maybe_add(c, elem, st, indices_key, should_add_elem,
622
+ decoder_space_usage, elem_hash, key_hash);
580
623
  return;
581
624
  }
582
625
 
583
626
  /* no elem, key in the table... fall back to literal emission */
584
- const bool should_add_key =
585
- !elem_interned && decoder_space_usage < MAX_DECODER_SPACE_USAGE;
627
+ const bool should_add_key = !elem_interned && decoder_space_available;
586
628
  if (should_add_elem || should_add_key) {
587
- emit_lithdr_incidx_v(c, 0, elem, st);
629
+ emit_lithdr_v<EmitLitHdrVType::INC_IDX_V>(c, elem, st);
588
630
  } else {
589
- emit_lithdr_noidx_v(c, 0, elem, st);
631
+ emit_lithdr_v<EmitLitHdrVType::NO_IDX_V>(c, elem, st);
590
632
  }
591
633
  if (should_add_elem) {
592
634
  add_elem(c, elem, decoder_space_usage, elem_hash, key_hash);
@@ -695,8 +737,12 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
695
737
  grpc_metadata_batch* metadata,
696
738
  const grpc_encode_header_options* options,
697
739
  grpc_slice_buffer* outbuf) {
698
- GPR_ASSERT(options->stream_id != 0);
699
-
740
+ /* grpc_chttp2_encode_header is called by FlushInitial/TrailingMetadata in
741
+ writing.cc. Specifically, on streams returned by NextStream(), which
742
+ returns streams from the list GRPC_CHTTP2_LIST_WRITABLE. The only way to be
743
+ added to the list is via grpc_chttp2_list_add_writable_stream(), which
744
+ validates that stream_id is not 0. So, this can be a debug assert. */
745
+ GPR_DEBUG_ASSERT(options->stream_id != 0);
700
746
  framer_state st;
701
747
  st.seen_regular_header = 0;
702
748
  st.stream_id = options->stream_id;