grpc 1.43.1 → 1.44.0.pre2

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 (382) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +84 -64
  3. data/include/grpc/grpc_security.h +10 -0
  4. data/include/grpc/impl/codegen/compression_types.h +0 -2
  5. data/include/grpc/impl/codegen/grpc_types.h +6 -0
  6. data/src/core/ext/filters/client_channel/backend_metric.h +1 -1
  7. data/src/core/ext/filters/client_channel/client_channel.cc +62 -68
  8. data/src/core/ext/filters/client_channel/client_channel.h +8 -8
  9. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +1 -1
  10. data/src/core/ext/filters/client_channel/config_selector.h +4 -4
  11. data/src/core/ext/filters/client_channel/dynamic_filters.h +1 -1
  12. data/src/core/ext/filters/client_channel/health/health_check_client.cc +16 -14
  13. data/src/core/ext/filters/client_channel/health/health_check_client.h +3 -3
  14. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +1 -1
  15. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +4 -3
  16. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +6 -5
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +3 -7
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +31 -32
  19. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h +0 -7
  20. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +1 -1
  21. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +1 -1
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +1 -1
  23. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +43 -29
  24. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +6 -2
  25. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +120 -68
  26. data/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +60 -48
  27. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +62 -61
  28. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +16 -11
  29. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +11 -5
  30. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +19 -15
  31. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.h +1 -1
  32. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +14 -12
  33. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +3 -2
  34. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +50 -105
  35. data/src/core/ext/filters/client_channel/lb_policy.cc +15 -14
  36. data/src/core/ext/filters/client_channel/lb_policy.h +19 -3
  37. data/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc +3 -3
  38. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +207 -81
  39. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +22 -12
  40. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +19 -15
  41. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +23 -38
  42. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +118 -207
  43. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +25 -32
  44. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +1 -1
  45. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +82 -73
  46. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +10 -10
  47. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +2 -1
  48. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +2 -5
  49. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +5 -5
  50. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +157 -67
  51. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +1 -1
  52. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +2 -2
  53. data/src/core/ext/filters/client_channel/retry_filter.cc +37 -64
  54. data/src/core/ext/filters/client_channel/retry_service_config.cc +1 -1
  55. data/src/core/ext/filters/client_channel/retry_service_config.h +1 -1
  56. data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +1 -1
  57. data/src/core/ext/filters/client_channel/subchannel.cc +12 -16
  58. data/src/core/ext/filters/client_channel/subchannel.h +2 -3
  59. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +37 -48
  60. data/src/core/ext/filters/fault_injection/service_config_parser.cc +6 -8
  61. data/src/core/ext/filters/fault_injection/service_config_parser.h +1 -1
  62. data/src/core/ext/filters/http/client/http_client_filter.cc +51 -122
  63. data/src/core/ext/filters/http/client_authority_filter.cc +8 -24
  64. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +42 -140
  65. data/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +5 -25
  66. data/src/core/ext/filters/http/server/http_server_filter.cc +50 -135
  67. data/src/core/ext/filters/message_size/message_size_filter.cc +1 -1
  68. data/src/core/ext/filters/message_size/message_size_filter.h +1 -1
  69. data/src/core/ext/filters/rbac/rbac_filter.cc +157 -0
  70. data/src/core/ext/filters/rbac/rbac_filter.h +74 -0
  71. data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +605 -0
  72. data/src/core/ext/filters/rbac/rbac_service_config_parser.h +70 -0
  73. data/src/core/ext/filters/server_config_selector/server_config_selector.h +3 -2
  74. data/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc +11 -6
  75. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +1 -1
  76. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +1 -1
  77. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +89 -29
  78. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc +0 -1
  79. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +45 -186
  80. data/src/core/ext/transport/chttp2/transport/frame_data.cc +0 -1
  81. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +341 -279
  82. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +69 -159
  83. data/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc +1 -1
  84. data/src/core/ext/transport/chttp2/transport/hpack_encoder_table.h +2 -0
  85. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +19 -32
  86. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +0 -1
  87. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +94 -1
  88. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +2 -24
  89. data/src/core/ext/transport/chttp2/transport/internal.h +0 -33
  90. data/src/core/ext/transport/chttp2/transport/parsing.cc +0 -6
  91. data/src/core/ext/transport/chttp2/transport/writing.cc +47 -116
  92. data/src/core/ext/transport/inproc/inproc_plugin.cc +0 -4
  93. data/src/core/ext/transport/inproc/inproc_transport.cc +11 -63
  94. data/src/core/ext/transport/inproc/inproc_transport.h +0 -3
  95. data/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c +61 -0
  96. data/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h +146 -0
  97. data/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c +188 -0
  98. data/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h +70 -0
  99. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c +56 -0
  100. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.h +40 -0
  101. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.c +154 -0
  102. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.h +95 -0
  103. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.c +58 -0
  104. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.h +55 -0
  105. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.c +44 -0
  106. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.h +40 -0
  107. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.c +153 -0
  108. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.h +100 -0
  109. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.c +75 -0
  110. data/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.h +55 -0
  111. data/src/core/ext/xds/upb_utils.h +65 -0
  112. data/src/core/ext/xds/xds_api.cc +81 -3458
  113. data/src/core/ext/xds/xds_api.h +56 -611
  114. data/src/core/ext/xds/xds_bootstrap.cc +189 -125
  115. data/src/core/ext/xds/xds_bootstrap.h +20 -15
  116. data/src/core/ext/xds/xds_certificate_provider.h +1 -0
  117. data/src/core/ext/xds/xds_channel_creds.cc +108 -0
  118. data/src/core/ext/xds/xds_channel_creds.h +50 -0
  119. data/src/core/ext/xds/xds_client.cc +584 -994
  120. data/src/core/ext/xds/xds_client.h +78 -135
  121. data/src/core/ext/xds/xds_cluster.cc +451 -0
  122. data/src/core/ext/xds/xds_cluster.h +111 -0
  123. data/src/core/ext/xds/xds_common_types.cc +388 -0
  124. data/src/core/ext/xds/xds_common_types.h +110 -0
  125. data/src/core/ext/xds/xds_endpoint.cc +364 -0
  126. data/src/core/ext/xds/xds_endpoint.h +135 -0
  127. data/src/core/ext/xds/xds_http_filters.cc +5 -0
  128. data/src/core/ext/xds/xds_http_rbac_filter.cc +563 -0
  129. data/src/core/ext/xds/xds_http_rbac_filter.h +54 -0
  130. data/src/core/ext/xds/xds_listener.cc +1036 -0
  131. data/src/core/ext/xds/xds_listener.h +220 -0
  132. data/src/core/ext/{transport/chttp2/transport/hpack_utils.h → xds/xds_resource_type.cc} +12 -9
  133. data/src/core/ext/xds/xds_resource_type.h +98 -0
  134. data/src/core/ext/xds/xds_resource_type_impl.h +87 -0
  135. data/src/core/ext/xds/xds_route_config.cc +993 -0
  136. data/src/core/ext/xds/xds_route_config.h +215 -0
  137. data/src/core/ext/xds/xds_routing.cc +11 -8
  138. data/src/core/ext/xds/xds_routing.h +8 -5
  139. data/src/core/ext/xds/xds_server_config_fetcher.cc +159 -99
  140. data/src/core/lib/address_utils/parse_address.cc +20 -0
  141. data/src/core/lib/address_utils/parse_address.h +5 -0
  142. data/src/core/lib/address_utils/sockaddr_utils.cc +33 -36
  143. data/src/core/lib/address_utils/sockaddr_utils.h +1 -16
  144. data/src/core/lib/backoff/backoff.cc +4 -30
  145. data/src/core/lib/backoff/backoff.h +3 -3
  146. data/src/core/lib/channel/channel_args.cc +0 -1
  147. data/src/core/lib/channel/channel_stack.cc +8 -0
  148. data/src/core/lib/channel/channel_stack.h +1 -1
  149. data/src/core/lib/channel/channel_stack_builder.cc +5 -9
  150. data/src/core/lib/channel/channel_stack_builder.h +4 -7
  151. data/src/core/lib/channel/channelz.cc +1 -0
  152. data/src/core/lib/compression/compression.cc +19 -111
  153. data/src/core/lib/compression/compression_internal.cc +142 -202
  154. data/src/core/lib/compression/compression_internal.h +64 -69
  155. data/src/core/lib/compression/message_compress.cc +11 -11
  156. data/src/core/lib/compression/message_compress.h +2 -2
  157. data/src/core/lib/gpr/useful.h +4 -0
  158. data/src/core/lib/gprpp/bitset.h +7 -0
  159. data/src/core/lib/gprpp/chunked_vector.h +45 -3
  160. data/src/core/lib/gprpp/status_helper.cc +20 -28
  161. data/src/core/lib/gprpp/status_helper.h +6 -19
  162. data/src/core/lib/gprpp/table.h +11 -0
  163. data/src/core/lib/http/httpcli.cc +37 -46
  164. data/src/core/lib/http/httpcli.h +3 -15
  165. data/src/core/lib/iomgr/call_combiner.cc +15 -4
  166. data/src/core/lib/iomgr/closure.h +29 -9
  167. data/src/core/lib/iomgr/combiner.cc +25 -3
  168. data/src/core/lib/iomgr/error.cc +2 -0
  169. data/src/core/lib/iomgr/error.h +3 -0
  170. data/src/core/lib/iomgr/event_engine/iomgr.cc +3 -2
  171. data/src/core/lib/iomgr/event_engine/resolved_address_internal.cc +6 -0
  172. data/src/core/lib/iomgr/event_engine/resolved_address_internal.h +2 -0
  173. data/src/core/lib/iomgr/event_engine/resolver.cc +66 -48
  174. data/src/core/lib/iomgr/event_engine/resolver.h +56 -0
  175. data/src/core/lib/iomgr/exec_ctx.cc +22 -9
  176. data/src/core/lib/iomgr/executor.cc +10 -1
  177. data/src/core/lib/iomgr/fork_posix.cc +3 -2
  178. data/src/core/lib/iomgr/iomgr_custom.cc +4 -1
  179. data/src/core/lib/iomgr/iomgr_posix.cc +2 -2
  180. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +2 -2
  181. data/src/core/lib/iomgr/iomgr_windows.cc +2 -2
  182. data/src/core/lib/iomgr/port.h +2 -2
  183. data/src/core/lib/iomgr/resolve_address.cc +5 -24
  184. data/src/core/lib/iomgr/resolve_address.h +47 -44
  185. data/src/core/lib/iomgr/resolve_address_custom.cc +131 -109
  186. data/src/core/lib/iomgr/resolve_address_custom.h +101 -19
  187. data/src/core/lib/iomgr/resolve_address_impl.h +59 -0
  188. data/src/core/lib/iomgr/resolve_address_posix.cc +82 -66
  189. data/src/core/lib/iomgr/resolve_address_posix.h +47 -0
  190. data/src/core/lib/iomgr/resolve_address_windows.cc +93 -74
  191. data/src/core/lib/iomgr/resolve_address_windows.h +47 -0
  192. data/src/core/lib/iomgr/resolved_address.h +39 -0
  193. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +1 -0
  194. data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +1 -0
  195. data/src/core/lib/iomgr/unix_sockets_posix.cc +22 -34
  196. data/src/core/lib/iomgr/unix_sockets_posix.h +4 -7
  197. data/src/core/lib/iomgr/unix_sockets_posix_noop.cc +6 -15
  198. data/src/core/lib/matchers/matchers.cc +1 -1
  199. data/src/core/lib/promise/activity.h +49 -20
  200. data/src/core/lib/promise/detail/status.h +5 -0
  201. data/src/core/{ext/filters/client_channel → lib/resolver}/resolver.cc +17 -25
  202. data/src/core/{ext/filters/client_channel → lib/resolver}/resolver.h +43 -44
  203. data/src/core/{ext/filters/client_channel → lib/resolver}/resolver_factory.h +10 -5
  204. data/src/core/{ext/filters/client_channel → lib/resolver}/resolver_registry.cc +3 -2
  205. data/src/core/{ext/filters/client_channel → lib/resolver}/resolver_registry.h +4 -5
  206. data/src/core/{ext/filters/client_channel → lib/resolver}/server_address.cc +1 -1
  207. data/src/core/{ext/filters/client_channel → lib/resolver}/server_address.h +4 -4
  208. data/src/core/lib/resource_quota/api.h +0 -1
  209. data/src/core/lib/{gprpp → resource_quota}/arena.cc +16 -13
  210. data/src/core/lib/{gprpp → resource_quota}/arena.h +24 -13
  211. data/src/core/lib/security/authorization/evaluate_args.cc +30 -15
  212. data/src/core/lib/security/authorization/evaluate_args.h +1 -0
  213. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +60 -0
  214. data/src/core/lib/security/authorization/grpc_authorization_engine.h +62 -0
  215. data/src/core/lib/security/authorization/matchers.cc +227 -0
  216. data/src/core/lib/security/authorization/matchers.h +211 -0
  217. data/src/core/lib/security/authorization/rbac_policy.cc +442 -0
  218. data/src/core/lib/security/authorization/rbac_policy.h +170 -0
  219. data/src/core/lib/security/context/security_context.cc +4 -2
  220. data/src/core/lib/security/context/security_context.h +1 -1
  221. data/src/core/lib/security/credentials/composite/composite_credentials.cc +5 -5
  222. data/src/core/lib/security/credentials/composite/composite_credentials.h +4 -3
  223. data/src/core/lib/security/credentials/credentials.h +10 -20
  224. data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +6 -9
  225. data/src/core/lib/security/credentials/external/external_account_credentials.cc +7 -9
  226. data/src/core/lib/security/credentials/external/external_account_credentials.h +2 -7
  227. data/src/core/lib/security/credentials/external/url_external_account_credentials.cc +2 -3
  228. data/src/core/lib/security/credentials/fake/fake_credentials.cc +5 -4
  229. data/src/core/lib/security/credentials/fake/fake_credentials.h +8 -7
  230. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +2 -5
  231. data/src/core/lib/security/credentials/iam/iam_credentials.cc +16 -19
  232. data/src/core/lib/security/credentials/iam/iam_credentials.h +6 -5
  233. data/src/core/lib/security/credentials/jwt/json_token.cc +4 -6
  234. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +16 -28
  235. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +8 -8
  236. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +6 -13
  237. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +44 -57
  238. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +13 -15
  239. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +6 -7
  240. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +5 -4
  241. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +1 -10
  242. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +6 -0
  243. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +7 -0
  244. data/src/core/lib/security/credentials/xds/xds_credentials.h +1 -1
  245. data/src/core/lib/security/security_connector/security_connector.cc +0 -4
  246. data/src/core/lib/security/security_connector/security_connector.h +5 -1
  247. data/src/core/lib/security/security_connector/ssl_utils.cc +14 -24
  248. data/src/core/lib/security/security_connector/ssl_utils.h +5 -14
  249. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +2 -3
  250. data/src/core/lib/security/transport/auth_filters.h +7 -0
  251. data/src/core/lib/security/transport/client_auth_filter.cc +53 -33
  252. data/src/core/lib/security/transport/server_auth_filter.cc +40 -35
  253. data/src/core/{ext → lib}/service_config/service_config.cc +2 -2
  254. data/src/core/{ext → lib}/service_config/service_config.h +4 -4
  255. data/src/core/{ext → lib}/service_config/service_config_call_data.h +5 -5
  256. data/src/core/{ext → lib}/service_config/service_config_parser.cc +1 -1
  257. data/src/core/{ext → lib}/service_config/service_config_parser.h +3 -3
  258. data/src/core/lib/slice/slice.cc +3 -1
  259. data/src/core/lib/slice/slice.h +43 -13
  260. data/src/core/lib/slice/slice_intern.cc +3 -101
  261. data/src/core/lib/slice/slice_internal.h +1 -2
  262. data/src/core/lib/slice/slice_refcount.h +4 -13
  263. data/src/core/lib/slice/slice_refcount_base.h +0 -16
  264. data/src/core/lib/surface/call.cc +140 -382
  265. data/src/core/lib/surface/call.h +4 -4
  266. data/src/core/lib/surface/channel.cc +42 -44
  267. data/src/core/lib/surface/channel.h +4 -4
  268. data/src/core/lib/surface/init.cc +0 -2
  269. data/src/core/lib/surface/lame_client.cc +0 -1
  270. data/src/core/lib/surface/server.cc +12 -29
  271. data/src/core/lib/surface/server.h +2 -2
  272. data/src/core/lib/surface/version.cc +2 -2
  273. data/src/core/lib/transport/error_utils.h +14 -0
  274. data/src/core/lib/transport/metadata_batch.h +799 -717
  275. data/src/core/lib/transport/parsed_metadata.cc +2 -0
  276. data/src/core/lib/transport/parsed_metadata.h +95 -92
  277. data/src/core/lib/transport/timeout_encoding.cc +200 -66
  278. data/src/core/lib/transport/timeout_encoding.h +40 -10
  279. data/src/core/lib/transport/transport.h +1 -1
  280. data/src/core/lib/transport/transport_op_string.cc +6 -39
  281. data/src/core/lib/uri/uri_parser.cc +223 -53
  282. data/src/core/lib/uri/uri_parser.h +36 -23
  283. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -3
  284. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -1
  285. data/src/core/tsi/ssl/session_cache/ssl_session.h +2 -4
  286. data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +3 -5
  287. data/src/core/tsi/ssl_transport_security.cc +53 -13
  288. data/src/core/tsi/ssl_transport_security.h +18 -6
  289. data/src/ruby/ext/grpc/extconf.rb +10 -3
  290. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  291. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
  292. data/src/ruby/lib/grpc/version.rb +1 -1
  293. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +2 -1
  294. data/third_party/abseil-cpp/absl/base/internal/fast_type_id.h +48 -0
  295. data/third_party/abseil-cpp/absl/random/bernoulli_distribution.h +200 -0
  296. data/third_party/abseil-cpp/absl/random/beta_distribution.h +427 -0
  297. data/third_party/abseil-cpp/absl/random/discrete_distribution.cc +98 -0
  298. data/third_party/abseil-cpp/absl/random/discrete_distribution.h +247 -0
  299. data/third_party/abseil-cpp/absl/random/distributions.h +452 -0
  300. data/third_party/abseil-cpp/absl/random/exponential_distribution.h +165 -0
  301. data/third_party/abseil-cpp/absl/random/gaussian_distribution.cc +104 -0
  302. data/third_party/abseil-cpp/absl/random/gaussian_distribution.h +275 -0
  303. data/third_party/abseil-cpp/absl/random/internal/distribution_caller.h +92 -0
  304. data/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h +268 -0
  305. data/third_party/abseil-cpp/absl/random/internal/fastmath.h +57 -0
  306. data/third_party/abseil-cpp/absl/random/internal/generate_real.h +144 -0
  307. data/third_party/abseil-cpp/absl/random/internal/iostream_state_saver.h +245 -0
  308. data/third_party/abseil-cpp/absl/random/internal/nonsecure_base.h +150 -0
  309. data/third_party/abseil-cpp/absl/random/internal/pcg_engine.h +308 -0
  310. data/third_party/abseil-cpp/absl/random/internal/platform.h +171 -0
  311. data/third_party/abseil-cpp/absl/random/internal/pool_urbg.cc +253 -0
  312. data/third_party/abseil-cpp/absl/random/internal/pool_urbg.h +131 -0
  313. data/third_party/abseil-cpp/absl/random/internal/randen.cc +91 -0
  314. data/third_party/abseil-cpp/absl/random/internal/randen.h +102 -0
  315. data/third_party/abseil-cpp/absl/random/internal/randen_detect.cc +221 -0
  316. data/third_party/abseil-cpp/absl/random/internal/randen_detect.h +33 -0
  317. data/third_party/abseil-cpp/absl/random/internal/randen_engine.h +239 -0
  318. data/third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc +526 -0
  319. data/third_party/abseil-cpp/absl/random/internal/randen_hwaes.h +50 -0
  320. data/third_party/abseil-cpp/absl/random/internal/randen_round_keys.cc +462 -0
  321. data/third_party/abseil-cpp/absl/random/internal/randen_slow.cc +471 -0
  322. data/third_party/abseil-cpp/absl/random/internal/randen_slow.h +40 -0
  323. data/third_party/abseil-cpp/absl/random/internal/randen_traits.h +88 -0
  324. data/third_party/abseil-cpp/absl/random/internal/salted_seed_seq.h +167 -0
  325. data/third_party/abseil-cpp/absl/random/internal/seed_material.cc +267 -0
  326. data/third_party/abseil-cpp/absl/random/internal/seed_material.h +104 -0
  327. data/third_party/abseil-cpp/absl/random/internal/traits.h +101 -0
  328. data/third_party/abseil-cpp/absl/random/internal/uniform_helper.h +244 -0
  329. data/third_party/abseil-cpp/absl/random/internal/wide_multiply.h +111 -0
  330. data/third_party/abseil-cpp/absl/random/log_uniform_int_distribution.h +257 -0
  331. data/third_party/abseil-cpp/absl/random/poisson_distribution.h +258 -0
  332. data/third_party/abseil-cpp/absl/random/random.h +189 -0
  333. data/third_party/abseil-cpp/absl/random/seed_gen_exception.cc +46 -0
  334. data/third_party/abseil-cpp/absl/random/seed_gen_exception.h +55 -0
  335. data/third_party/abseil-cpp/absl/random/seed_sequences.cc +29 -0
  336. data/third_party/abseil-cpp/absl/random/seed_sequences.h +110 -0
  337. data/third_party/abseil-cpp/absl/random/uniform_int_distribution.h +275 -0
  338. data/third_party/abseil-cpp/absl/random/uniform_real_distribution.h +202 -0
  339. data/third_party/abseil-cpp/absl/random/zipf_distribution.h +271 -0
  340. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_enc.c +1 -0
  341. data/third_party/boringssl-with-bazel/src/crypto/base64/base64.c +13 -0
  342. data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa.c +21 -0
  343. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/cipher/cipher.c +12 -0
  344. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/ecdsa.c +1 -2
  345. data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +2 -2
  346. data/third_party/boringssl-with-bazel/src/crypto/mem.c +1 -1
  347. data/third_party/boringssl-with-bazel/src/crypto/pkcs7/pkcs7.c +29 -0
  348. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/internal.h +0 -1
  349. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/pkcs8.c +1 -1
  350. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/pkcs8_x509.c +1 -1
  351. data/third_party/boringssl-with-bazel/src/include/openssl/base64.h +8 -0
  352. data/third_party/boringssl-with-bazel/src/include/openssl/cipher.h +13 -1
  353. data/third_party/boringssl-with-bazel/src/include/openssl/dsa.h +10 -0
  354. data/third_party/boringssl-with-bazel/src/include/openssl/hpke.h +1 -1
  355. data/third_party/boringssl-with-bazel/src/include/openssl/pkcs7.h +9 -4
  356. data/third_party/boringssl-with-bazel/src/include/openssl/pkcs8.h +6 -1
  357. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +23 -2
  358. data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +4 -0
  359. data/third_party/xxhash/xxhash.h +607 -352
  360. metadata +149 -77
  361. data/src/core/ext/transport/chttp2/transport/hpack_encoder_index.h +0 -107
  362. data/src/core/ext/transport/chttp2/transport/hpack_utils.cc +0 -46
  363. data/src/core/ext/transport/chttp2/transport/popularity_count.h +0 -60
  364. data/src/core/lib/compression/algorithm_metadata.h +0 -62
  365. data/src/core/lib/compression/compression_args.cc +0 -140
  366. data/src/core/lib/compression/compression_args.h +0 -58
  367. data/src/core/lib/compression/stream_compression.cc +0 -81
  368. data/src/core/lib/compression/stream_compression.h +0 -117
  369. data/src/core/lib/compression/stream_compression_gzip.cc +0 -231
  370. data/src/core/lib/compression/stream_compression_gzip.h +0 -28
  371. data/src/core/lib/compression/stream_compression_identity.cc +0 -91
  372. data/src/core/lib/compression/stream_compression_identity.h +0 -29
  373. data/src/core/lib/security/credentials/credentials_metadata.cc +0 -61
  374. data/src/core/lib/slice/static_slice.cc +0 -377
  375. data/src/core/lib/slice/static_slice.h +0 -300
  376. data/src/core/lib/transport/metadata.cc +0 -714
  377. data/src/core/lib/transport/metadata.h +0 -449
  378. data/src/core/lib/transport/metadata_batch.cc +0 -99
  379. data/src/core/lib/transport/static_metadata.cc +0 -1032
  380. data/src/core/lib/transport/static_metadata.h +0 -322
  381. data/src/core/lib/transport/status_metadata.cc +0 -63
  382. data/src/core/lib/transport/status_metadata.h +0 -48
@@ -23,54 +23,26 @@
23
23
 
24
24
  #include <stdbool.h>
25
25
 
26
+ #include <limits>
27
+
26
28
  #include "absl/strings/match.h"
27
29
  #include "absl/strings/str_join.h"
28
30
  #include "absl/types/optional.h"
29
31
 
30
32
  #include <grpc/grpc.h>
31
33
  #include <grpc/slice.h>
34
+ #include <grpc/status.h>
32
35
  #include <grpc/support/time.h>
33
36
 
37
+ #include "src/core/lib/compression/compression_internal.h"
34
38
  #include "src/core/lib/gprpp/chunked_vector.h"
35
39
  #include "src/core/lib/gprpp/table.h"
36
40
  #include "src/core/lib/iomgr/exec_ctx.h"
37
41
  #include "src/core/lib/slice/slice.h"
38
42
  #include "src/core/lib/surface/validate_metadata.h"
39
- #include "src/core/lib/transport/metadata.h"
40
43
  #include "src/core/lib/transport/parsed_metadata.h"
41
- #include "src/core/lib/transport/static_metadata.h"
42
44
  #include "src/core/lib/transport/timeout_encoding.h"
43
45
 
44
- typedef struct grpc_linked_mdelem {
45
- grpc_linked_mdelem() {}
46
-
47
- grpc_mdelem md;
48
- struct grpc_linked_mdelem* next = nullptr;
49
- struct grpc_linked_mdelem* prev = nullptr;
50
- void* reserved;
51
- } grpc_linked_mdelem;
52
-
53
- typedef struct grpc_mdelem_list {
54
- size_t count;
55
- size_t default_count; // Number of default keys.
56
- grpc_linked_mdelem* head;
57
- grpc_linked_mdelem* tail;
58
- } grpc_mdelem_list;
59
-
60
- struct grpc_filtered_mdelem {
61
- grpc_error_handle error;
62
- grpc_mdelem md;
63
- };
64
- #define GRPC_FILTERED_ERROR(error) \
65
- { (error), GRPC_MDNULL }
66
- #define GRPC_FILTERED_MDELEM(md) \
67
- { GRPC_ERROR_NONE, (md) }
68
- #define GRPC_FILTERED_REMOVE() \
69
- { GRPC_ERROR_NONE, GRPC_MDNULL }
70
-
71
- grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src,
72
- grpc_mdelem md);
73
-
74
46
  namespace grpc_core {
75
47
 
76
48
  // grpc-timeout metadata trait.
@@ -81,15 +53,17 @@ namespace grpc_core {
81
53
  // to name this in MetadataMap, but ultimately once the transition is done we
82
54
  // should not need to.
83
55
  struct GrpcTimeoutMetadata {
56
+ static constexpr bool kRepeatable = false;
84
57
  using ValueType = grpc_millis;
85
58
  using MementoType = grpc_millis;
86
59
  static absl::string_view key() { return "grpc-timeout"; }
87
- static MementoType ParseMemento(Slice value) {
88
- grpc_millis timeout;
89
- if (GPR_UNLIKELY(!grpc_http2_decode_timeout(value.c_slice(), &timeout))) {
90
- timeout = GRPC_MILLIS_INF_FUTURE;
60
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
61
+ auto timeout = ParseTimeout(value);
62
+ if (!timeout.has_value()) {
63
+ on_error("invalid value", value);
64
+ return GRPC_MILLIS_INF_FUTURE;
91
65
  }
92
- return timeout;
66
+ return *timeout;
93
67
  }
94
68
  static ValueType MementoToValue(MementoType timeout) {
95
69
  if (timeout == GRPC_MILLIS_INF_FUTURE) {
@@ -98,15 +72,14 @@ struct GrpcTimeoutMetadata {
98
72
  return ExecCtx::Get()->Now() + timeout;
99
73
  }
100
74
  static Slice Encode(ValueType x) {
101
- char timeout[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
102
- grpc_http2_encode_timeout(x, timeout);
103
- return Slice::FromCopiedString(timeout);
75
+ return Timeout::FromDuration(x - ExecCtx::Get()->Now()).Encode();
104
76
  }
105
77
  static MementoType DisplayValue(MementoType x) { return x; }
106
78
  };
107
79
 
108
80
  // TE metadata trait.
109
81
  struct TeMetadata {
82
+ static constexpr bool kRepeatable = false;
110
83
  // HTTP2 says that TE can either be empty or "trailers".
111
84
  // Empty means this trait is not included, "trailers" means kTrailers, and
112
85
  // kInvalid is used to remember an invalid value.
@@ -116,17 +89,19 @@ struct TeMetadata {
116
89
  };
117
90
  using MementoType = ValueType;
118
91
  static absl::string_view key() { return "te"; }
119
- static MementoType ParseMemento(Slice value) {
92
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
120
93
  auto out = kInvalid;
121
94
  if (value == "trailers") {
122
95
  out = kTrailers;
96
+ } else {
97
+ on_error("invalid value", value);
123
98
  }
124
99
  return out;
125
100
  }
126
101
  static ValueType MementoToValue(MementoType te) { return te; }
127
102
  static StaticSlice Encode(ValueType x) {
128
103
  GPR_ASSERT(x == kTrailers);
129
- return StaticSlice(GRPC_MDSTR_TRAILERS);
104
+ return StaticSlice::FromStaticString("trailers");
130
105
  }
131
106
  static const char* DisplayValue(MementoType te) {
132
107
  switch (te) {
@@ -138,10 +113,223 @@ struct TeMetadata {
138
113
  }
139
114
  };
140
115
 
116
+ // content-type metadata trait.
117
+ struct ContentTypeMetadata {
118
+ static constexpr bool kRepeatable = false;
119
+ // gRPC says that content-type can be application/grpc[;something]
120
+ // Core has only ever verified the prefix.
121
+ // IF we want to start verifying more, we can expand this type.
122
+ enum ValueType {
123
+ kApplicationGrpc,
124
+ kEmpty,
125
+ kInvalid,
126
+ };
127
+ using MementoType = ValueType;
128
+ static absl::string_view key() { return "content-type"; }
129
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
130
+ auto out = kInvalid;
131
+ auto value_string = value.as_string_view();
132
+ if (value_string == "application/grpc") {
133
+ out = kApplicationGrpc;
134
+ } else if (absl::StartsWith(value_string, "application/grpc;")) {
135
+ out = kApplicationGrpc;
136
+ } else if (absl::StartsWith(value_string, "application/grpc+")) {
137
+ out = kApplicationGrpc;
138
+ } else if (value_string.empty()) {
139
+ out = kEmpty;
140
+ } else {
141
+ on_error("invalid value", value);
142
+ }
143
+ return out;
144
+ }
145
+ static ValueType MementoToValue(MementoType content_type) {
146
+ return content_type;
147
+ }
148
+ static StaticSlice Encode(ValueType x) {
149
+ switch (x) {
150
+ case kEmpty:
151
+ return StaticSlice::FromStaticString("");
152
+ case kApplicationGrpc:
153
+ return StaticSlice::FromStaticString("application/grpc");
154
+ case kInvalid:
155
+ abort();
156
+ }
157
+ GPR_UNREACHABLE_CODE(
158
+ return StaticSlice::FromStaticString("unrepresentable value"));
159
+ }
160
+ static const char* DisplayValue(MementoType content_type) {
161
+ switch (content_type) {
162
+ case ValueType::kApplicationGrpc:
163
+ return "application/grpc";
164
+ case ValueType::kEmpty:
165
+ return "";
166
+ default:
167
+ return "<discarded-invalid-value>";
168
+ }
169
+ }
170
+ };
171
+
172
+ // scheme metadata trait.
173
+ struct HttpSchemeMetadata {
174
+ static constexpr bool kRepeatable = false;
175
+ enum ValueType {
176
+ kHttp,
177
+ kHttps,
178
+ kInvalid,
179
+ };
180
+ using MementoType = ValueType;
181
+ static absl::string_view key() { return ":scheme"; }
182
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
183
+ return Parse(value.as_string_view(), on_error);
184
+ }
185
+ static ValueType Parse(absl::string_view value,
186
+ MetadataParseErrorFn on_error) {
187
+ if (value == "http") {
188
+ return kHttp;
189
+ } else if (value == "https") {
190
+ return kHttps;
191
+ }
192
+ on_error("invalid value", Slice::FromCopiedBuffer(value));
193
+ return kInvalid;
194
+ }
195
+ static ValueType MementoToValue(MementoType content_type) {
196
+ return content_type;
197
+ }
198
+ static StaticSlice Encode(ValueType x) {
199
+ switch (x) {
200
+ case kHttp:
201
+ return StaticSlice::FromStaticString("http");
202
+ case kHttps:
203
+ return StaticSlice::FromStaticString("https");
204
+ default:
205
+ abort();
206
+ }
207
+ }
208
+ static const char* DisplayValue(MementoType content_type) {
209
+ switch (content_type) {
210
+ case kHttp:
211
+ return "http";
212
+ case kHttps:
213
+ return "https";
214
+ default:
215
+ return "<discarded-invalid-value>";
216
+ }
217
+ }
218
+ };
219
+
220
+ // method metadata trait.
221
+ struct HttpMethodMetadata {
222
+ static constexpr bool kRepeatable = false;
223
+ enum ValueType {
224
+ kPost,
225
+ kPut,
226
+ kGet,
227
+ kInvalid,
228
+ };
229
+ using MementoType = ValueType;
230
+ static absl::string_view key() { return ":method"; }
231
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
232
+ auto out = kInvalid;
233
+ auto value_string = value.as_string_view();
234
+ if (value_string == "POST") {
235
+ out = kPost;
236
+ } else if (value_string == "PUT") {
237
+ out = kPut;
238
+ } else if (value_string == "GET") {
239
+ out = kGet;
240
+ } else {
241
+ on_error("invalid value", value);
242
+ }
243
+ return out;
244
+ }
245
+ static ValueType MementoToValue(MementoType content_type) {
246
+ return content_type;
247
+ }
248
+ static StaticSlice Encode(ValueType x) {
249
+ switch (x) {
250
+ case kPost:
251
+ return StaticSlice::FromStaticString("POST");
252
+ case kPut:
253
+ return StaticSlice::FromStaticString("PUT");
254
+ case kGet:
255
+ return StaticSlice::FromStaticString("GET");
256
+ default:
257
+ abort();
258
+ }
259
+ }
260
+ static const char* DisplayValue(MementoType content_type) {
261
+ switch (content_type) {
262
+ case kPost:
263
+ return "POST";
264
+ case kPut:
265
+ return "PUT";
266
+ case kGet:
267
+ return "GET";
268
+ default:
269
+ return "<discarded-invalid-value>";
270
+ }
271
+ }
272
+ };
273
+
274
+ // Base type for metadata pertaining to a single compression algorithm
275
+ // (e.g., "grpc-encoding").
276
+ struct CompressionAlgorithmBasedMetadata {
277
+ using ValueType = grpc_compression_algorithm;
278
+ using MementoType = ValueType;
279
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
280
+ auto algorithm = ParseCompressionAlgorithm(value.as_string_view());
281
+ if (!algorithm.has_value()) {
282
+ on_error("invalid value", value);
283
+ return GRPC_COMPRESS_NONE;
284
+ }
285
+ return *algorithm;
286
+ }
287
+ static ValueType MementoToValue(MementoType x) { return x; }
288
+ static Slice Encode(ValueType x) {
289
+ GPR_ASSERT(x != GRPC_COMPRESS_ALGORITHMS_COUNT);
290
+ return Slice::FromStaticString(CompressionAlgorithmAsString(x));
291
+ }
292
+ static const char* DisplayValue(MementoType x) {
293
+ if (const char* p = CompressionAlgorithmAsString(x)) {
294
+ return p;
295
+ } else {
296
+ return "<discarded-invalid-value>";
297
+ }
298
+ }
299
+ };
300
+
301
+ // grpc-encoding metadata trait.
302
+ struct GrpcEncodingMetadata : public CompressionAlgorithmBasedMetadata {
303
+ static constexpr bool kRepeatable = false;
304
+ static absl::string_view key() { return "grpc-encoding"; }
305
+ };
306
+
307
+ // grpc-internal-encoding-request metadata trait.
308
+ struct GrpcInternalEncodingRequest : public CompressionAlgorithmBasedMetadata {
309
+ static constexpr bool kRepeatable = false;
310
+ static absl::string_view key() { return "grpc-internal-encoding-request"; }
311
+ };
312
+
313
+ // grpc-accept-encoding metadata trait.
314
+ struct GrpcAcceptEncodingMetadata {
315
+ static constexpr bool kRepeatable = false;
316
+ static absl::string_view key() { return "grpc-accept-encoding"; }
317
+ using ValueType = CompressionAlgorithmSet;
318
+ using MementoType = ValueType;
319
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn) {
320
+ return CompressionAlgorithmSet::FromString(value.as_string_view());
321
+ }
322
+ static ValueType MementoToValue(MementoType x) { return x; }
323
+ static Slice Encode(ValueType x) { return x.ToSlice(); }
324
+ static std::string DisplayValue(MementoType x) { return x.ToString(); }
325
+ };
326
+
141
327
  struct SimpleSliceBasedMetadata {
142
328
  using ValueType = Slice;
143
329
  using MementoType = Slice;
144
- static MementoType ParseMemento(Slice value) { return value.TakeOwned(); }
330
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn) {
331
+ return value.TakeOwned();
332
+ }
145
333
  static ValueType MementoToValue(MementoType value) { return value; }
146
334
  static Slice Encode(const ValueType& x) { return x.Ref(); }
147
335
  static absl::string_view DisplayValue(const MementoType& value) {
@@ -151,39 +339,167 @@ struct SimpleSliceBasedMetadata {
151
339
 
152
340
  // user-agent metadata trait.
153
341
  struct UserAgentMetadata : public SimpleSliceBasedMetadata {
342
+ static constexpr bool kRepeatable = false;
154
343
  static absl::string_view key() { return "user-agent"; }
155
344
  };
156
345
 
157
346
  // grpc-message metadata trait.
158
347
  struct GrpcMessageMetadata : public SimpleSliceBasedMetadata {
348
+ static constexpr bool kRepeatable = false;
159
349
  static absl::string_view key() { return "grpc-message"; }
160
350
  };
161
351
 
162
352
  // host metadata trait.
163
353
  struct HostMetadata : public SimpleSliceBasedMetadata {
354
+ static constexpr bool kRepeatable = false;
164
355
  static absl::string_view key() { return "host"; }
165
356
  };
166
357
 
167
358
  // x-endpoint-load-metrics-bin metadata trait.
168
359
  struct XEndpointLoadMetricsBinMetadata : public SimpleSliceBasedMetadata {
360
+ static constexpr bool kRepeatable = false;
169
361
  static absl::string_view key() { return "x-endpoint-load-metrics-bin"; }
170
362
  };
171
363
 
172
364
  // grpc-server-stats-bin metadata trait.
173
365
  struct GrpcServerStatsBinMetadata : public SimpleSliceBasedMetadata {
366
+ static constexpr bool kRepeatable = false;
174
367
  static absl::string_view key() { return "grpc-server-stats-bin"; }
175
368
  };
176
369
 
177
370
  // grpc-trace-bin metadata trait.
178
371
  struct GrpcTraceBinMetadata : public SimpleSliceBasedMetadata {
372
+ static constexpr bool kRepeatable = false;
179
373
  static absl::string_view key() { return "grpc-trace-bin"; }
180
374
  };
181
375
 
182
376
  // grpc-tags-bin metadata trait.
183
377
  struct GrpcTagsBinMetadata : public SimpleSliceBasedMetadata {
378
+ static constexpr bool kRepeatable = false;
184
379
  static absl::string_view key() { return "grpc-tags-bin"; }
185
380
  };
186
381
 
382
+ // :authority metadata trait.
383
+ struct HttpAuthorityMetadata : public SimpleSliceBasedMetadata {
384
+ static constexpr bool kRepeatable = false;
385
+ static absl::string_view key() { return ":authority"; }
386
+ };
387
+
388
+ // :path metadata trait.
389
+ struct HttpPathMetadata : public SimpleSliceBasedMetadata {
390
+ static constexpr bool kRepeatable = false;
391
+ static absl::string_view key() { return ":path"; }
392
+ };
393
+
394
+ // We separate SimpleIntBasedMetadata into two pieces: one that does not depend
395
+ // on the invalid value, and one that does. This allows the compiler to easily
396
+ // see the functions that are shared, and helps reduce code bloat here.
397
+ template <typename Int>
398
+ struct SimpleIntBasedMetadataBase {
399
+ using ValueType = Int;
400
+ using MementoType = Int;
401
+ static ValueType MementoToValue(MementoType value) { return value; }
402
+ static Slice Encode(ValueType x) { return Slice::FromInt64(x); }
403
+ static Int DisplayValue(MementoType x) { return x; }
404
+ };
405
+
406
+ template <typename Int, Int kInvalidValue>
407
+ struct SimpleIntBasedMetadata : public SimpleIntBasedMetadataBase<Int> {
408
+ static constexpr Int invalid_value() { return kInvalidValue; }
409
+ static Int ParseMemento(Slice value, MetadataParseErrorFn on_error) {
410
+ Int out;
411
+ if (!absl::SimpleAtoi(value.as_string_view(), &out)) {
412
+ on_error("not an integer", value);
413
+ out = kInvalidValue;
414
+ }
415
+ return out;
416
+ }
417
+ };
418
+
419
+ // grpc-status metadata trait.
420
+ struct GrpcStatusMetadata
421
+ : public SimpleIntBasedMetadata<grpc_status_code, GRPC_STATUS_UNKNOWN> {
422
+ static constexpr bool kRepeatable = false;
423
+ static absl::string_view key() { return "grpc-status"; }
424
+ };
425
+
426
+ // grpc-previous-rpc-attempts metadata trait.
427
+ struct GrpcPreviousRpcAttemptsMetadata
428
+ : public SimpleIntBasedMetadata<uint32_t, 0> {
429
+ static constexpr bool kRepeatable = false;
430
+ static absl::string_view key() { return "grpc-previous-rpc-attempts"; }
431
+ };
432
+
433
+ // grpc-retry-pushback-ms metadata trait.
434
+ struct GrpcRetryPushbackMsMetadata
435
+ : public SimpleIntBasedMetadata<grpc_millis, GRPC_MILLIS_INF_PAST> {
436
+ static constexpr bool kRepeatable = false;
437
+ static absl::string_view key() { return "grpc-retry-pushback-ms"; }
438
+ };
439
+
440
+ // :status metadata trait.
441
+ // TODO(ctiller): consider moving to uint16_t
442
+ struct HttpStatusMetadata : public SimpleIntBasedMetadata<uint32_t, 0> {
443
+ static constexpr bool kRepeatable = false;
444
+ static absl::string_view key() { return ":status"; }
445
+ };
446
+
447
+ // "secret" metadata trait used to pass load balancing token between filters.
448
+ // This should not be exposed outside of gRPC core.
449
+ class GrpcLbClientStats;
450
+ struct GrpcLbClientStatsMetadata {
451
+ static constexpr bool kRepeatable = false;
452
+ static absl::string_view key() { return "grpclb_client_stats"; }
453
+ using ValueType = GrpcLbClientStats*;
454
+ using MementoType = ValueType;
455
+ static ValueType MementoToValue(MementoType value) { return value; }
456
+ static Slice Encode(ValueType) { abort(); }
457
+ static const char* DisplayValue(MementoType) { return "<internal-lb-stats>"; }
458
+ static MementoType ParseMemento(Slice, MetadataParseErrorFn) {
459
+ return nullptr;
460
+ }
461
+ };
462
+
463
+ // lb-token metadata
464
+ struct LbTokenMetadata : public SimpleSliceBasedMetadata {
465
+ static constexpr bool kRepeatable = false;
466
+ static absl::string_view key() { return "lb-token"; }
467
+ };
468
+
469
+ // lb-cost-bin metadata
470
+ struct LbCostBinMetadata {
471
+ static constexpr bool kRepeatable = true;
472
+ static absl::string_view key() { return "lb-cost-bin"; }
473
+ struct ValueType {
474
+ double cost;
475
+ std::string name;
476
+ };
477
+ using MementoType = ValueType;
478
+ static ValueType MementoToValue(MementoType value) { return value; }
479
+ static Slice Encode(const ValueType& x) {
480
+ auto slice =
481
+ MutableSlice::CreateUninitialized(sizeof(double) + x.name.length());
482
+ memcpy(slice.data(), &x.cost, sizeof(double));
483
+ memcpy(slice.data() + sizeof(double), x.name.data(), x.name.length());
484
+ return Slice(std::move(slice));
485
+ }
486
+ static std::string DisplayValue(MementoType x) {
487
+ return absl::StrCat(x.name, ":", x.cost);
488
+ }
489
+ static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
490
+ if (value.length() < sizeof(double)) {
491
+ on_error("too short", value);
492
+ return {0, ""};
493
+ }
494
+ MementoType out;
495
+ memcpy(&out.cost, value.data(), sizeof(double));
496
+ out.name = std::string(
497
+ reinterpret_cast<const char*>(value.data()) + sizeof(double),
498
+ value.length() - sizeof(double));
499
+ return out;
500
+ }
501
+ };
502
+
187
503
  namespace metadata_detail {
188
504
 
189
505
  // Helper type - maps a string name to a trait.
@@ -193,7 +509,7 @@ struct NameLookup;
193
509
  template <typename Trait, typename... Traits>
194
510
  struct NameLookup<Trait, Traits...> {
195
511
  // Call op->Found(Trait()) if op->name == Trait::key() for some Trait in
196
- // Traits. If not found, call op->NotFount().
512
+ // Traits. If not found, call op->NotFound().
197
513
  template <typename Op>
198
514
  static auto Lookup(absl::string_view key, Op* op)
199
515
  -> decltype(op->Found(Trait())) {
@@ -219,9 +535,11 @@ struct NameLookup<> {
219
535
  template <typename ParseMementoFn, typename MementoToValueFn>
220
536
  struct ParseValue {
221
537
  template <ParseMementoFn parse_memento, MementoToValueFn memento_to_value>
222
- static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value)
223
- -> decltype(memento_to_value(parse_memento(std::move(*value)))) {
224
- return memento_to_value(parse_memento(std::move(*value)));
538
+ static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value,
539
+ MetadataParseErrorFn on_error)
540
+ -> decltype(memento_to_value(parse_memento(std::move(*value),
541
+ on_error))) {
542
+ return memento_to_value(parse_memento(std::move(*value), on_error));
225
543
  }
226
544
  };
227
545
 
@@ -231,36 +549,44 @@ struct ParseValue {
231
549
  template <typename Container>
232
550
  class ParseHelper {
233
551
  public:
234
- ParseHelper(Slice value, size_t transport_size)
235
- : value_(std::move(value)), transport_size_(transport_size) {}
552
+ ParseHelper(Slice value, MetadataParseErrorFn on_error, size_t transport_size)
553
+ : value_(std::move(value)),
554
+ on_error_(on_error),
555
+ transport_size_(transport_size) {}
236
556
 
237
557
  template <typename Trait>
238
- ParsedMetadata<Container> Found(Trait trait) {
558
+ GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> Found(Trait trait) {
239
559
  return ParsedMetadata<Container>(
240
- trait, Trait::ParseMemento(std::move(value_)), transport_size_);
560
+ trait,
561
+ ParseValueToMemento<typename Trait::MementoType, Trait::ParseMemento>(),
562
+ transport_size_);
241
563
  }
242
564
 
243
565
  GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> NotFound(
244
566
  absl::string_view key) {
245
- return ParsedMetadata<Container>(
246
- grpc_mdelem_from_slices(grpc_slice_intern(grpc_slice_from_static_buffer(
247
- key.data(), key.size())),
248
- value_.TakeCSlice()));
567
+ return ParsedMetadata<Container>(Slice::FromCopiedString(key),
568
+ std::move(value_));
249
569
  }
250
570
 
251
571
  private:
572
+ template <typename T, T (*parse_memento)(Slice, MetadataParseErrorFn)>
573
+ GPR_ATTRIBUTE_NOINLINE T ParseValueToMemento() {
574
+ return parse_memento(std::move(value_), on_error_);
575
+ }
576
+
252
577
  Slice value_;
578
+ MetadataParseErrorFn on_error_;
253
579
  const size_t transport_size_;
254
580
  };
255
581
 
256
582
  // This is an "Op" type for NameLookup.
257
- // Used for MetadataMap::Parse, its Found/NotFound methods turn a slice into a
583
+ // Used for MetadataMap::Append, its Found/NotFound methods turn a slice into a
258
584
  // value and add it to a container.
259
585
  template <typename Container>
260
586
  class AppendHelper {
261
587
  public:
262
- AppendHelper(Container* container, Slice value)
263
- : container_(container), value_(std::move(value)) {}
588
+ AppendHelper(Container* container, Slice value, MetadataParseErrorFn on_error)
589
+ : container_(container), value_(std::move(value)), on_error_(on_error) {}
264
590
 
265
591
  template <typename Trait>
266
592
  GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
@@ -268,50 +594,232 @@ class AppendHelper {
268
594
  trait, ParseValue<decltype(Trait::ParseMemento),
269
595
  decltype(Trait::MementoToValue)>::
270
596
  template Parse<Trait::ParseMemento, Trait::MementoToValue>(
271
- &value_));
597
+ &value_, on_error_));
272
598
  }
273
599
 
274
- void NotFound(absl::string_view key) {
275
- GPR_ASSERT(GRPC_ERROR_NONE ==
276
- container_->Append(grpc_mdelem_from_slices(
277
- grpc_slice_intern(
278
- grpc_slice_from_static_buffer(key.data(), key.length())),
279
- value_.TakeCSlice())));
600
+ GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
601
+ container_->AppendUnknown(key, std::move(value_));
280
602
  }
281
603
 
282
604
  private:
283
605
  Container* const container_;
284
606
  Slice value_;
607
+ MetadataParseErrorFn on_error_;
608
+ };
609
+
610
+ // This is an "Op" type for NameLookup.
611
+ // Used for MetadataMap::Remove, its Found/NotFound methods remove a key from
612
+ // the container.
613
+ template <typename Container>
614
+ class RemoveHelper {
615
+ public:
616
+ explicit RemoveHelper(Container* container) : container_(container) {}
617
+
618
+ template <typename Trait>
619
+ GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
620
+ container_->Remove(trait);
621
+ }
622
+
623
+ GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
624
+ container_->RemoveUnknown(key);
625
+ }
626
+
627
+ private:
628
+ Container* const container_;
629
+ };
630
+
631
+ // This is an "Op" type for NameLookup.
632
+ // Used for MetadataMap::GetStringValue, its Found/NotFound methods generated a
633
+ // string value from the container.
634
+ template <typename Container>
635
+ class GetStringValueHelper {
636
+ public:
637
+ explicit GetStringValueHelper(const Container* container,
638
+ std::string* backing)
639
+ : container_(container), backing_(backing) {}
640
+
641
+ template <typename Trait>
642
+ GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
643
+ Trait::kRepeatable == false &&
644
+ std::is_same<Slice, typename Trait::ValueType>::value,
645
+ absl::optional<absl::string_view>>
646
+ Found(Trait) {
647
+ const auto* value = container_->get_pointer(Trait());
648
+ if (value == nullptr) return absl::nullopt;
649
+ return value->as_string_view();
650
+ }
651
+
652
+ template <typename Trait>
653
+ GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
654
+ Trait::kRepeatable == true &&
655
+ !std::is_same<Slice, typename Trait::ValueType>::value,
656
+ absl::optional<absl::string_view>>
657
+ Found(Trait) {
658
+ const auto* value = container_->get_pointer(Trait());
659
+ if (value == nullptr) return absl::nullopt;
660
+ backing_->clear();
661
+ for (const auto& v : *value) {
662
+ if (!backing_->empty()) backing_->push_back(',');
663
+ auto new_segment = Trait::Encode(v);
664
+ backing_->append(new_segment.begin(), new_segment.end());
665
+ }
666
+ return *backing_;
667
+ }
668
+
669
+ template <typename Trait>
670
+ GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
671
+ Trait::kRepeatable == false &&
672
+ !std::is_same<Slice, typename Trait::ValueType>::value,
673
+ absl::optional<absl::string_view>>
674
+ Found(Trait) {
675
+ const auto* value = container_->get_pointer(Trait());
676
+ if (value == nullptr) return absl::nullopt;
677
+ *backing_ = std::string(Trait::Encode(*value).as_string_view());
678
+ return *backing_;
679
+ }
680
+
681
+ GPR_ATTRIBUTE_NOINLINE absl::optional<absl::string_view> NotFound(
682
+ absl::string_view key) {
683
+ return container_->GetStringValueUnknown(key, backing_);
684
+ }
685
+
686
+ private:
687
+ const Container* const container_;
688
+ std::string* backing_;
689
+ };
690
+
691
+ // Generate a strong type for metadata values per trait.
692
+ template <typename Which, typename Ignored = void>
693
+ struct Value;
694
+
695
+ template <typename Which>
696
+ struct Value<Which, absl::enable_if_t<Which::kRepeatable == false, void>> {
697
+ Value() = default;
698
+ explicit Value(const typename Which::ValueType& value) : value(value) {}
699
+ explicit Value(typename Which::ValueType&& value)
700
+ : value(std::forward<typename Which::ValueType>(value)) {}
701
+ Value(const Value&) = delete;
702
+ Value& operator=(const Value&) = delete;
703
+ Value(Value&&) noexcept = default;
704
+ Value& operator=(Value&& other) noexcept {
705
+ value = std::move(other.value);
706
+ return *this;
707
+ }
708
+ template <typename Encoder>
709
+ void EncodeTo(Encoder* encoder) const {
710
+ encoder->Encode(Which(), value);
711
+ }
712
+ using StorageType = typename Which::ValueType;
713
+ GPR_NO_UNIQUE_ADDRESS StorageType value;
714
+ };
715
+
716
+ template <typename Which>
717
+ struct Value<Which, absl::enable_if_t<Which::kRepeatable == true, void>> {
718
+ Value() = default;
719
+ explicit Value(const typename Which::ValueType& value) {
720
+ this->value.push_back(value);
721
+ }
722
+ explicit Value(typename Which::ValueType&& value) {
723
+ this->value.emplace_back(std::forward<typename Which::ValueType>(value));
724
+ }
725
+ Value(const Value&) = delete;
726
+ Value& operator=(const Value&) = delete;
727
+ Value(Value&& other) noexcept : value(std::move(other.value)) {}
728
+ Value& operator=(Value&& other) noexcept {
729
+ value = std::move(other.value);
730
+ return *this;
731
+ }
732
+ template <typename Encoder>
733
+ void EncodeTo(Encoder* encoder) const {
734
+ for (const auto& v : value) {
735
+ encoder->Encode(Which(), v);
736
+ }
737
+ }
738
+ using StorageType = absl::InlinedVector<typename Which::ValueType, 1>;
739
+ StorageType value;
740
+ };
741
+
742
+ // Encoder to copy some metadata
743
+ template <typename Output>
744
+ class CopySink {
745
+ public:
746
+ explicit CopySink(Output* dst) : dst_(dst) {}
747
+
748
+ template <class T, class V>
749
+ void Encode(T trait, V value) {
750
+ dst_->Set(trait, value);
751
+ }
752
+
753
+ template <class T>
754
+ void Encode(T trait, const Slice& value) {
755
+ dst_->Set(trait, std::move(value.AsOwned()));
756
+ }
757
+
758
+ void Encode(const Slice& key, const Slice& value) {
759
+ dst_->AppendUnknown(key.as_string_view(), value.Ref());
760
+ }
761
+
762
+ private:
763
+ Output* dst_;
285
764
  };
286
765
 
287
766
  } // namespace metadata_detail
288
767
 
768
+ // Helper function for encoders
769
+ // Given a metadata trait, convert the value to a slice.
770
+ template <typename Which>
771
+ absl::enable_if_t<std::is_same<typename Which::ValueType, Slice>::value,
772
+ const Slice&>
773
+ MetadataValueAsSlice(const Slice& slice) {
774
+ return slice;
775
+ }
776
+
777
+ template <typename Which>
778
+ absl::enable_if_t<!std::is_same<typename Which::ValueType, Slice>::value, Slice>
779
+ MetadataValueAsSlice(typename Which::ValueType value) {
780
+ return Slice(Which::Encode(value));
781
+ }
782
+
289
783
  // MetadataMap encodes the mapping of metadata keys to metadata values.
290
- // Right now the API presented is the minimal one that will allow us to
291
- // substitute this type for grpc_metadata_batch in a relatively easy fashion. At
292
- // that point we'll start iterating this API into something that's ergonomic
293
- // again, whilst minimally holding the performance bar already set (and
294
- // hopefully improving some things).
295
- // In the meantime, we're not going to invest much time in ephemeral API
296
- // documentation, so if you must use one of these APIs and it's not obvious
297
- // how, reach out to ctiller.
298
784
  //
299
- // MetadataMap takes a list of traits. Each of these trait objects defines
300
- // one metadata field that is used by core, and so should have more specialized
301
- // handling than just using the generic APIs.
785
+ // MetadataMap takes a derived class and list of traits. Each of these trait
786
+ // objects defines one metadata field that is used by core, and so should have
787
+ // more specialized handling than just using the generic APIs.
788
+ //
789
+ // MetadataMap is the backing type for some derived type via the curiously
790
+ // recursive template pattern. This is because many types consumed by
791
+ // MetadataMap require the container type to operate on, and many of those
792
+ // types are instantiated one per trait. A naive implementation without the
793
+ // Derived type would, for traits A,B,C, then instantiate for some
794
+ // T<Container, Trait>:
795
+ // - T<MetadataMap<A,B,C>, A>,
796
+ // - T<MetadataMap<A,B,C>, B>,
797
+ // - T<MetadataMap<A,B,C>, C>.
798
+ // Since these types ultimately need to be recorded in the .dynstr segment
799
+ // for dynamic linkers (if gRPC is linked as a static library) this would
800
+ // create O(N^2) bytes of symbols even in stripped libraries. To avoid this
801
+ // we use the derived type (e.g. grpc_metadata_batch right now) to capture
802
+ // the container type, and we would write T<grpc_metadata_batch, A>, etc...
803
+ // Note that now the container type uses a number of bytes that is independent
804
+ // of the number of traits, and so we return to a linear symbol table growth
805
+ // function.
302
806
  //
303
807
  // Each trait object has the following signature:
304
808
  // // Traits for the grpc-xyz metadata field:
305
809
  // struct GrpcXyzMetadata {
306
810
  // // The type that's stored on MetadataBatch
307
811
  // using ValueType = ...;
812
+ // // Can this metadata field be repeated?
813
+ // static constexpr bool kRepeatable = ...;
308
814
  // // The type that's stored in compression/decompression tables
309
815
  // using MementoType = ...;
310
816
  // // The string key for this metadata type (for transports that require it)
311
817
  // static absl::string_view key() { return "grpc-xyz"; }
312
818
  // // Parse a memento from a slice
313
819
  // // Takes ownership of value
314
- // static MementoType ParseMemento(Slice value) { ... }
820
+ // // Calls fn in the case of an error that should be reported to the user
821
+ // static MementoType ParseMemento(Slice value, MementoParseErrorFn fn) { ...
822
+ // }
315
823
  // // Convert a memento to a value
316
824
  // static ValueType MementoToValue(MementoType memento) { ... }
317
825
  // // Convert a value to its canonical text wire format (the format that
@@ -341,7 +849,7 @@ class AppendHelper {
341
849
  // for grpc-timeout we make the memento the timeout expressed on the wire, but
342
850
  // we make the value the timestamp of when the timeout will expire (i.e. the
343
851
  // deadline).
344
- template <typename... Traits>
852
+ template <class Derived, typename... Traits>
345
853
  class MetadataMap {
346
854
  public:
347
855
  explicit MetadataMap(Arena* arena);
@@ -350,7 +858,10 @@ class MetadataMap {
350
858
  MetadataMap(const MetadataMap&) = delete;
351
859
  MetadataMap& operator=(const MetadataMap&) = delete;
352
860
  MetadataMap(MetadataMap&&) noexcept;
353
- MetadataMap& operator=(MetadataMap&&) noexcept;
861
+ // We never create MetadataMap directly, instead we create Derived, but we
862
+ // want to be able to move it without redeclaring this.
863
+ // NOLINTNEXTLINE(misc-unconventional-assign-operator)
864
+ Derived& operator=(MetadataMap&&) noexcept;
354
865
 
355
866
  // Encode this metadata map into some encoder.
356
867
  // For each field that is set in the MetadataMap, call
@@ -367,17 +878,23 @@ class MetadataMap {
367
878
  // transitions.
368
879
  template <typename Encoder>
369
880
  void Encode(Encoder* encoder) const {
370
- for (auto* l = list_.head; l; l = l->next) {
371
- encoder->Encode(l->md);
372
- }
373
881
  table_.ForEach(EncodeWrapper<Encoder>{encoder});
882
+ for (const auto& unk : unknown_) {
883
+ encoder->Encode(unk.first, unk.second);
884
+ }
374
885
  }
375
886
 
887
+ // Similar to Encode, but targeted at logging: for each metadatum,
888
+ // call f(key, value) as absl::string_views.
889
+ void Log(absl::FunctionRef<void(absl::string_view, absl::string_view)> log_fn)
890
+ const;
891
+
376
892
  // Get the pointer to the value of some known metadata.
377
893
  // Returns nullptr if the metadata is not present.
378
894
  // Causes a compilation error if Which is not an element of Traits.
379
895
  template <typename Which>
380
- const typename Which::ValueType* get_pointer(Which) const {
896
+ const typename metadata_detail::Value<Which>::StorageType* get_pointer(
897
+ Which) const {
381
898
  if (auto* p = table_.template get<Value<Which>>()) return &p->value;
382
899
  return nullptr;
383
900
  }
@@ -386,11 +903,20 @@ class MetadataMap {
386
903
  // Returns nullptr if the metadata is not present.
387
904
  // Causes a compilation error if Which is not an element of Traits.
388
905
  template <typename Which>
389
- typename Which::ValueType* get_pointer(Which) {
906
+ typename metadata_detail::Value<Which>::StorageType* get_pointer(Which) {
390
907
  if (auto* p = table_.template get<Value<Which>>()) return &p->value;
391
908
  return nullptr;
392
909
  }
393
910
 
911
+ // Get the pointer to the value of some known metadata.
912
+ // Adds the default value for the metadata is not present.
913
+ // Causes a compilation error if Which is not an element of Traits.
914
+ template <typename Which>
915
+ typename metadata_detail::Value<Which>::StorageType* GetOrCreatePointer(
916
+ Which) {
917
+ return &table_.template get_or_create<Value<Which>>()->value;
918
+ }
919
+
394
920
  // Get the value of some known metadata.
395
921
  // Returns nullopt if the metadata is not present.
396
922
  // Causes a compilation error if Which is not an element of Traits.
@@ -403,9 +929,14 @@ class MetadataMap {
403
929
  // Set the value of some known metadata.
404
930
  // Returns a pointer to the new value.
405
931
  template <typename Which, typename... Args>
406
- typename Which::ValueType* Set(Which, Args&&... args) {
407
- return &table_.template set<Value<Which>>(std::forward<Args>(args)...)
408
- ->value;
932
+ absl::enable_if_t<Which::kRepeatable == false, void> Set(Which,
933
+ Args&&... args) {
934
+ table_.template set<Value<Which>>(std::forward<Args>(args)...);
935
+ }
936
+ template <typename Which, typename... Args>
937
+ absl::enable_if_t<Which::kRepeatable == true, void> Set(Which,
938
+ Args&&... args) {
939
+ GetOrCreatePointer(Which())->emplace_back(std::forward<Args>(args)...);
409
940
  }
410
941
 
411
942
  // Remove a specific piece of known metadata.
@@ -414,13 +945,31 @@ class MetadataMap {
414
945
  table_.template clear<Value<Which>>();
415
946
  }
416
947
 
948
+ // Remove some metadata by name
949
+ void Remove(absl::string_view key) {
950
+ metadata_detail::RemoveHelper<Derived> helper(static_cast<Derived*>(this));
951
+ metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
952
+ }
953
+
954
+ void Remove(const char* key) { Remove(absl::string_view(key)); }
955
+
956
+ // Retrieve some metadata by name
957
+ absl::optional<absl::string_view> GetStringValue(absl::string_view name,
958
+ std::string* buffer) const {
959
+ metadata_detail::GetStringValueHelper<Derived> helper(
960
+ static_cast<const Derived*>(this), buffer);
961
+ return metadata_detail::NameLookup<Traits...>::Lookup(name, &helper);
962
+ }
963
+
417
964
  // Extract a piece of known metadata.
418
965
  // Returns nullopt if the metadata was not present, or the value if it was.
419
966
  // The same as:
420
967
  // auto value = m.get(T());
421
968
  // m.Remove(T());
422
969
  template <typename Which>
423
- absl::optional<typename Which::ValueType> Take(Which which) {
970
+ absl::enable_if_t<Which::kRepeatable == false,
971
+ absl::optional<typename Which::ValueType>>
972
+ Take(Which which) {
424
973
  if (auto* p = get_pointer(which)) {
425
974
  absl::optional<typename Which::ValueType> value(std::move(*p));
426
975
  Remove(which);
@@ -429,150 +978,61 @@ class MetadataMap {
429
978
  return {};
430
979
  }
431
980
 
981
+ // Extract repeated known metadata.
982
+ // Returns an empty vector if the metadata was not present.
983
+ template <typename Which>
984
+ absl::enable_if_t<Which::kRepeatable == true,
985
+ typename metadata_detail::Value<Which>::StorageType>
986
+ Take(Which which) {
987
+ if (auto* p = get_pointer(which)) {
988
+ typename Value<Which>::StorageType value = std::move(*p);
989
+ Remove(which);
990
+ return value;
991
+ }
992
+ return {};
993
+ }
994
+
432
995
  // Parse metadata from a key/value pair, and return an object representing
433
996
  // that result.
434
997
  // TODO(ctiller): key should probably be an absl::string_view.
435
998
  // Once we don't care about interning anymore, make that change!
436
- static ParsedMetadata<MetadataMap> Parse(absl::string_view key, Slice value,
437
- uint32_t transport_size) {
438
- metadata_detail::ParseHelper<MetadataMap> helper(value.TakeOwned(),
439
- transport_size);
999
+ static ParsedMetadata<Derived> Parse(absl::string_view key, Slice value,
1000
+ uint32_t transport_size,
1001
+ MetadataParseErrorFn on_error) {
1002
+ metadata_detail::ParseHelper<Derived> helper(value.TakeOwned(), on_error,
1003
+ transport_size);
440
1004
  return metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
441
1005
  }
442
1006
 
443
1007
  // Set a value from a parsed metadata object.
444
- GRPC_MUST_USE_RESULT grpc_error_handle
445
- Set(const ParsedMetadata<MetadataMap>& m) {
446
- return m.SetOnContainer(this);
1008
+ void Set(const ParsedMetadata<Derived>& m) {
1009
+ m.SetOnContainer(static_cast<Derived*>(this));
447
1010
  }
448
1011
 
449
1012
  // Append a key/value pair - takes ownership of value
450
- void Append(absl::string_view key, Slice value) {
451
- metadata_detail::AppendHelper<MetadataMap> helper(this, value.TakeOwned());
1013
+ void Append(absl::string_view key, Slice value,
1014
+ MetadataParseErrorFn on_error) {
1015
+ metadata_detail::AppendHelper<Derived> helper(static_cast<Derived*>(this),
1016
+ value.TakeOwned(), on_error);
452
1017
  metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
453
1018
  }
454
1019
 
455
- //
456
- // All APIs below this point are subject to change.
457
- //
458
-
459
- template <typename F>
460
- void ForEach(F f) const {
461
- for (auto* l = list_.head; l; l = l->next) {
462
- f(l->md);
463
- }
464
- }
465
-
466
- template <typename F>
467
- grpc_error_handle Filter(F f, const char* composite_error_string) {
468
- grpc_linked_mdelem* l = list_.head;
469
- grpc_error_handle error = GRPC_ERROR_NONE;
470
- auto add_error = [&](grpc_error_handle new_error) {
471
- if (new_error == GRPC_ERROR_NONE) return;
472
- if (error == GRPC_ERROR_NONE) {
473
- error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(composite_error_string);
474
- }
475
- error = grpc_error_add_child(error, new_error);
476
- };
477
- while (l) {
478
- grpc_linked_mdelem* next = l->next;
479
- grpc_filtered_mdelem new_mdelem = f(l->md);
480
- add_error(new_mdelem.error);
481
- if (GRPC_MDISNULL(new_mdelem.md)) {
482
- Remove(l);
483
- } else if (new_mdelem.md.payload != l->md.payload) {
484
- add_error(Substitute(l, new_mdelem.md));
485
- }
486
- l = next;
487
- }
488
- return error;
489
- }
490
-
491
- GRPC_MUST_USE_RESULT grpc_error_handle Append(grpc_mdelem md) {
492
- return AddTail(elem_storage_.EmplaceBack(), md);
493
- }
494
-
495
- GRPC_MUST_USE_RESULT grpc_error_handle ReplaceOrAppend(grpc_slice key,
496
- grpc_slice value) {
497
- if (ReplaceIfExists(key, value)) return GRPC_ERROR_NONE;
498
- return Append(grpc_mdelem_from_slices(key, value));
499
- }
500
-
501
- // Set key to value if it exists and return true, otherwise return false.
502
- // If this function returns true, it takes ownership of key and value.
503
- // If this function returns false, it does not take ownership of key nor
504
- // value.
505
- bool ReplaceIfExists(grpc_slice key, grpc_slice value);
506
-
507
1020
  void Clear();
508
- bool empty() const { return count() == 0; }
509
-
510
- size_t count() const { return list_.count + table_.count(); }
511
- size_t non_deadline_count() const { return list_.count; }
512
- size_t default_count() const { return list_.default_count; }
513
-
514
1021
  size_t TransportSize() const;
515
-
516
- void Remove(grpc_linked_mdelem* storage);
517
- void Remove(grpc_metadata_batch_callouts_index idx);
518
-
519
- absl::optional<grpc_slice> Remove(grpc_slice key);
520
-
521
- grpc_error_handle Substitute(grpc_linked_mdelem* storage,
522
- grpc_mdelem new_mdelem);
523
-
524
- absl::optional<absl::string_view> GetValue(
525
- absl::string_view target_key, std::string* concatenated_value) const;
526
-
527
- grpc_error_handle LinkHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
528
- grpc_error_handle LinkHead(grpc_linked_mdelem* storage,
529
- grpc_metadata_batch_callouts_index idx)
530
- GRPC_MUST_USE_RESULT;
531
- grpc_error_handle LinkTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
532
- grpc_error_handle LinkTail(grpc_linked_mdelem* storage,
533
- grpc_metadata_batch_callouts_index idx)
534
- GRPC_MUST_USE_RESULT;
535
-
536
- grpc_error_handle AddHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
537
- grpc_error_handle AddHead(grpc_linked_mdelem* storage,
538
- grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
539
- grpc_error_handle AddTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT;
540
- grpc_error_handle AddTail(grpc_linked_mdelem* storage,
541
- grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
542
-
543
- void CopyFrom(MetadataMap* src, grpc_linked_mdelem* storage);
544
-
545
- #ifndef NDEBUG
546
- void AssertOk();
547
- #else
548
- void AssertOk() {}
549
- #endif
550
-
551
- // TODO(ctiller): the following explicit deadline handling methods are
552
- // deprecated in terms of the traits based APIs.
553
- grpc_millis deadline() const {
554
- return get(GrpcTimeoutMetadata()).value_or(GRPC_MILLIS_INF_FUTURE);
555
- };
556
-
557
- const grpc_metadata_batch_callouts* legacy_index() const { return &idx_; }
1022
+ Derived Copy() const;
1023
+ bool empty() const { return table_.empty() && unknown_.empty(); }
1024
+ size_t count() const { return table_.count() + unknown_.size(); }
558
1025
 
559
1026
  private:
560
- // Generate a strong type for metadata values per trait.
1027
+ friend class metadata_detail::AppendHelper<Derived>;
1028
+ friend class metadata_detail::GetStringValueHelper<Derived>;
1029
+ friend class metadata_detail::RemoveHelper<Derived>;
1030
+ friend class metadata_detail::CopySink<Derived>;
1031
+ friend class ParsedMetadata<Derived>;
1032
+
561
1033
  template <typename Which>
562
- struct Value {
563
- Value() = default;
564
- explicit Value(const typename Which::ValueType& value) : value(value) {}
565
- explicit Value(typename Which::ValueType&& value)
566
- : value(std::forward<typename Which::ValueType>(value)) {}
567
- Value(const Value&) = delete;
568
- Value& operator=(const Value&) = delete;
569
- Value(Value&&) noexcept = default;
570
- Value& operator=(Value&& other) noexcept {
571
- value = std::move(other.value);
572
- return *this;
573
- }
574
- GPR_NO_UNIQUE_ADDRESS typename Which::ValueType value;
575
- };
1034
+ using Value = metadata_detail::Value<Which>;
1035
+
576
1036
  // Callable for the ForEach in Encode() -- for each value, call the
577
1037
  // appropriate encoder method.
578
1038
  template <typename Encoder>
@@ -580,551 +1040,173 @@ class MetadataMap {
580
1040
  Encoder* encoder;
581
1041
  template <typename Which>
582
1042
  void operator()(const Value<Which>& which) {
583
- encoder->Encode(Which(), which.value);
1043
+ which.EncodeTo(encoder);
584
1044
  }
585
1045
  };
586
1046
 
587
- void AssertValidCallouts();
588
- grpc_error_handle LinkCallout(grpc_linked_mdelem* storage,
589
- grpc_metadata_batch_callouts_index idx)
590
- GRPC_MUST_USE_RESULT;
591
- grpc_error_handle MaybeLinkCallout(grpc_linked_mdelem* storage)
592
- GRPC_MUST_USE_RESULT;
593
- void MaybeUnlinkCallout(grpc_linked_mdelem* storage);
594
-
595
- static void assert_valid_list(grpc_mdelem_list* list) {
596
- #ifndef NDEBUG
597
- grpc_linked_mdelem* l;
598
-
599
- GPR_ASSERT((list->head == nullptr) == (list->tail == nullptr));
600
- if (!list->head) return;
601
- GPR_ASSERT(list->head->prev == nullptr);
602
- GPR_ASSERT(list->tail->next == nullptr);
603
- GPR_ASSERT((list->head == list->tail) == (list->head->next == nullptr));
604
-
605
- size_t verified_count = 0;
606
- for (l = list->head; l; l = l->next) {
607
- GPR_ASSERT(!GRPC_MDISNULL(l->md));
608
- GPR_ASSERT((l->prev == nullptr) == (l == list->head));
609
- GPR_ASSERT((l->next == nullptr) == (l == list->tail));
610
- if (l->next) GPR_ASSERT(l->next->prev == l);
611
- if (l->prev) GPR_ASSERT(l->prev->next == l);
612
- verified_count++;
1047
+ // Encoder to compute TransportSize
1048
+ class TransportSizeEncoder {
1049
+ public:
1050
+ void Encode(const Slice& key, const Slice& value) {
1051
+ size_ += key.length() + value.length() + 32;
613
1052
  }
614
- GPR_ASSERT(list->count == verified_count);
615
- #else
616
- // Avoid unused-parameter warning for debug-only parameter
617
- (void)list;
618
- #endif /* NDEBUG */
619
- }
620
-
621
- static grpc_error_handle GPR_ATTRIBUTE_NOINLINE
622
- error_with_md(grpc_mdelem md) {
623
- return grpc_attach_md_to_error(
624
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"),
625
- md);
626
- }
627
-
628
- static void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) {
629
- assert_valid_list(list);
630
- GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md));
631
- storage->prev = nullptr;
632
- storage->next = list->head;
633
- storage->reserved = nullptr;
634
- if (list->head != nullptr) {
635
- list->head->prev = storage;
636
- } else {
637
- list->tail = storage;
638
- }
639
- list->head = storage;
640
- list->count++;
641
- assert_valid_list(list);
642
- }
643
-
644
- static void link_tail(grpc_mdelem_list* list, grpc_linked_mdelem* storage) {
645
- assert_valid_list(list);
646
- GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md));
647
- storage->prev = list->tail;
648
- storage->next = nullptr;
649
- storage->reserved = nullptr;
650
- if (list->tail != nullptr) {
651
- list->tail->next = storage;
652
- } else {
653
- list->head = storage;
654
- }
655
- list->tail = storage;
656
- list->count++;
657
- assert_valid_list(list);
658
- }
659
1053
 
660
- static void unlink_storage(grpc_mdelem_list* list,
661
- grpc_linked_mdelem* storage) {
662
- assert_valid_list(list);
663
- if (storage->prev != nullptr) {
664
- storage->prev->next = storage->next;
665
- } else {
666
- list->head = storage->next;
667
- }
668
- if (storage->next != nullptr) {
669
- storage->next->prev = storage->prev;
670
- } else {
671
- list->tail = storage->prev;
1054
+ template <typename Which>
1055
+ void Encode(Which, const typename Which::ValueType& value) {
1056
+ Add(Which(), value);
672
1057
  }
673
- list->count--;
674
- assert_valid_list(list);
675
- }
676
1058
 
677
- // Table of known metadata types.
678
- Table<Value<Traits>...> table_;
679
- /** Metadata elements in this batch */
680
- grpc_mdelem_list list_;
681
- grpc_metadata_batch_callouts idx_;
682
- // Backing store for added metadata.
683
- ChunkedVector<grpc_linked_mdelem, 10> elem_storage_;
684
- };
685
-
686
- template <typename... Traits>
687
- void MetadataMap<Traits...>::AssertValidCallouts() {
688
- #ifndef NDEBUG
689
- for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) {
690
- grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md));
691
- grpc_metadata_batch_callouts_index callout_idx =
692
- GRPC_BATCH_INDEX_OF(key_interned);
693
- if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) {
694
- GPR_ASSERT(idx_.array[callout_idx] == l);
1059
+ void Encode(ContentTypeMetadata,
1060
+ const typename ContentTypeMetadata::ValueType& value) {
1061
+ if (value == ContentTypeMetadata::kInvalid) return;
1062
+ Add(ContentTypeMetadata(), value);
695
1063
  }
696
- grpc_slice_unref_internal(key_interned);
697
- }
698
- #endif
699
- }
700
-
701
- #ifndef NDEBUG
702
- template <typename... Traits>
703
- void MetadataMap<Traits...>::AssertOk() {
704
- assert_valid_list(&list_);
705
- }
706
- #endif /* NDEBUG */
707
-
708
- template <typename... Traits>
709
- MetadataMap<Traits...>::MetadataMap(Arena* arena) : elem_storage_(arena) {
710
- memset(&list_, 0, sizeof(list_));
711
- memset(&idx_, 0, sizeof(idx_));
712
- }
713
-
714
- template <typename... Traits>
715
- MetadataMap<Traits...>::MetadataMap(MetadataMap&& other) noexcept
716
- : table_(std::move(other.table_)) {
717
- list_ = other.list_;
718
- idx_ = other.idx_;
719
- memset(&other.list_, 0, sizeof(list_));
720
- memset(&other.idx_, 0, sizeof(idx_));
721
- }
722
-
723
- template <typename... Traits>
724
- MetadataMap<Traits...>& MetadataMap<Traits...>::operator=(
725
- MetadataMap&& other) noexcept {
726
- Clear();
727
- table_ = std::move(other.table_);
728
- list_ = other.list_;
729
- idx_ = other.idx_;
730
- memset(&other.list_, 0, sizeof(list_));
731
- memset(&other.idx_, 0, sizeof(idx_));
732
- return *this;
733
- }
734
1064
 
735
- template <typename... Traits>
736
- MetadataMap<Traits...>::~MetadataMap() {
737
- AssertValidCallouts();
738
- for (auto* l = list_.head; l; l = l->next) {
739
- GRPC_MDELEM_UNREF(l->md);
740
- }
741
- }
1065
+ size_t size() const { return size_; }
742
1066
 
743
- template <typename... Traits>
744
- absl::optional<grpc_slice> MetadataMap<Traits...>::Remove(grpc_slice key) {
745
- for (auto* l = list_.head; l; l = l->next) {
746
- if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) {
747
- auto out = grpc_slice_ref_internal(GRPC_MDVALUE(l->md));
748
- Remove(l);
749
- return out;
1067
+ private:
1068
+ template <typename Which>
1069
+ void Add(Which, const typename Which::ValueType& value) {
1070
+ size_ += Which::key().length() + Which::Encode(value).length() + 32;
750
1071
  }
751
- }
752
- return {};
753
- }
754
-
755
- template <typename... Traits>
756
- grpc_error_handle MetadataMap<Traits...>::LinkCallout(
757
- grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) {
758
- AssertValidCallouts();
759
- GPR_DEBUG_ASSERT(idx >= 0 && idx < GRPC_BATCH_CALLOUTS_COUNT);
760
- if (GPR_LIKELY(idx_.array[idx] == nullptr)) {
761
- ++list_.default_count;
762
- idx_.array[idx] = storage;
763
- AssertValidCallouts();
764
- return GRPC_ERROR_NONE;
765
- }
766
- AssertValidCallouts();
767
- return error_with_md(storage->md);
768
- }
769
-
770
- template <typename... Traits>
771
- grpc_error_handle MetadataMap<Traits...>::MaybeLinkCallout(
772
- grpc_linked_mdelem* storage) {
773
- grpc_metadata_batch_callouts_index idx =
774
- GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
775
- if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
776
- return GRPC_ERROR_NONE;
777
- }
778
- return LinkCallout(storage, idx);
779
- }
780
-
781
- template <typename... Traits>
782
- void MetadataMap<Traits...>::MaybeUnlinkCallout(grpc_linked_mdelem* storage) {
783
- grpc_metadata_batch_callouts_index idx =
784
- GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
785
- if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
786
- return;
787
- }
788
- --list_.default_count;
789
- GPR_DEBUG_ASSERT(idx_.array[idx] != nullptr);
790
- idx_.array[idx] = nullptr;
791
- }
792
-
793
- template <typename... Traits>
794
- grpc_error_handle MetadataMap<Traits...>::AddHead(grpc_linked_mdelem* storage,
795
- grpc_mdelem elem_to_add) {
796
- GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
797
- storage->md = elem_to_add;
798
- return LinkHead(storage);
799
- }
800
-
801
- template <typename... Traits>
802
- grpc_error_handle MetadataMap<Traits...>::LinkHead(
803
- grpc_linked_mdelem* storage) {
804
- AssertValidCallouts();
805
- grpc_error_handle err = MaybeLinkCallout(storage);
806
- if (err != GRPC_ERROR_NONE) {
807
- AssertValidCallouts();
808
- return err;
809
- }
810
- link_head(&list_, storage);
811
- AssertValidCallouts();
812
- return GRPC_ERROR_NONE;
813
- }
814
-
815
- // TODO(arjunroy): Need to revisit this and see what guarantees exist between
816
- // C-core and the internal-metadata subsystem. E.g. can we ensure a particular
817
- // metadata is never added twice, even in the presence of user supplied data?
818
- template <typename... Traits>
819
- grpc_error_handle MetadataMap<Traits...>::LinkHead(
820
- grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) {
821
- GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx);
822
- AssertValidCallouts();
823
- grpc_error_handle err = LinkCallout(storage, idx);
824
- if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
825
- AssertValidCallouts();
826
- return err;
827
- }
828
- link_head(&list_, storage);
829
- AssertValidCallouts();
830
- return GRPC_ERROR_NONE;
831
- }
832
1072
 
833
- template <typename... Traits>
834
- grpc_error_handle MetadataMap<Traits...>::AddTail(grpc_linked_mdelem* storage,
835
- grpc_mdelem elem_to_add) {
836
- GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
837
- storage->md = elem_to_add;
838
- return LinkTail(storage);
839
- }
840
-
841
- template <typename... Traits>
842
- grpc_error_handle MetadataMap<Traits...>::LinkTail(
843
- grpc_linked_mdelem* storage) {
844
- AssertValidCallouts();
845
- grpc_error_handle err = MaybeLinkCallout(storage);
846
- if (err != GRPC_ERROR_NONE) {
847
- AssertValidCallouts();
848
- return err;
849
- }
850
- link_tail(&list_, storage);
851
- AssertValidCallouts();
852
- return GRPC_ERROR_NONE;
853
- }
1073
+ uint32_t size_ = 0;
1074
+ };
854
1075
 
855
- template <typename... Traits>
856
- grpc_error_handle MetadataMap<Traits...>::LinkTail(
857
- grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) {
858
- GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx);
859
- AssertValidCallouts();
860
- grpc_error_handle err = LinkCallout(storage, idx);
861
- if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) {
862
- AssertValidCallouts();
863
- return err;
864
- }
865
- link_tail(&list_, storage);
866
- AssertValidCallouts();
867
- return GRPC_ERROR_NONE;
868
- }
1076
+ // Encoder to log some metadata
1077
+ class LogEncoder {
1078
+ public:
1079
+ explicit LogEncoder(
1080
+ absl::FunctionRef<void(absl::string_view, absl::string_view)> log_fn)
1081
+ : log_fn_(log_fn) {}
869
1082
 
870
- template <typename... Traits>
871
- void MetadataMap<Traits...>::Remove(grpc_linked_mdelem* storage) {
872
- AssertValidCallouts();
873
- MaybeUnlinkCallout(storage);
874
- unlink_storage(&list_, storage);
875
- GRPC_MDELEM_UNREF(storage->md);
876
- AssertValidCallouts();
877
- }
1083
+ template <typename Which>
1084
+ void Encode(Which, const typename Which::ValueType& value) {
1085
+ log_fn_(Which::key(), absl::StrCat(Which::DisplayValue(value)));
1086
+ }
878
1087
 
879
- template <typename... Traits>
880
- void MetadataMap<Traits...>::Remove(grpc_metadata_batch_callouts_index idx) {
881
- AssertValidCallouts();
882
- if (idx_.array[idx] == nullptr) return;
883
- --list_.default_count;
884
- unlink_storage(&list_, idx_.array[idx]);
885
- GRPC_MDELEM_UNREF(idx_.array[idx]->md);
886
- idx_.array[idx] = nullptr;
887
- AssertValidCallouts();
888
- }
1088
+ void Encode(const Slice& key, const Slice& value) {
1089
+ log_fn_(key.as_string_view(), value.as_string_view());
1090
+ }
889
1091
 
890
- template <typename... Traits>
891
- absl::optional<absl::string_view> MetadataMap<Traits...>::GetValue(
892
- absl::string_view target_key, std::string* concatenated_value) const {
893
- // Find all values for the specified key.
894
- absl::InlinedVector<absl::string_view, 1> values;
895
- for (grpc_linked_mdelem* md = list_.head; md != nullptr; md = md->next) {
896
- absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md));
897
- absl::string_view value = StringViewFromSlice(GRPC_MDVALUE(md->md));
898
- if (target_key == key) values.push_back(value);
899
- }
900
- // If none found, no match.
901
- if (values.empty()) return absl::nullopt;
902
- // If exactly one found, return it as-is.
903
- if (values.size() == 1) return values.front();
904
- // If more than one found, concatenate the values, using
905
- // *concatenated_values as a temporary holding place for the
906
- // concatenated string.
907
- *concatenated_value = absl::StrJoin(values, ",");
908
- return *concatenated_value;
909
- }
1092
+ private:
1093
+ absl::FunctionRef<void(absl::string_view, absl::string_view)> log_fn_;
1094
+ };
910
1095
 
911
- template <typename... Traits>
912
- grpc_error_handle MetadataMap<Traits...>::Substitute(
913
- grpc_linked_mdelem* storage, grpc_mdelem new_mdelem) {
914
- AssertValidCallouts();
915
- grpc_error_handle error = GRPC_ERROR_NONE;
916
- grpc_mdelem old_mdelem = storage->md;
917
- if (!grpc_slice_eq(GRPC_MDKEY(new_mdelem), GRPC_MDKEY(old_mdelem))) {
918
- MaybeUnlinkCallout(storage);
919
- storage->md = new_mdelem;
920
- error = MaybeLinkCallout(storage);
921
- if (error != GRPC_ERROR_NONE) {
922
- unlink_storage(&list_, storage);
923
- GRPC_MDELEM_UNREF(storage->md);
924
- }
925
- } else {
926
- storage->md = new_mdelem;
1096
+ void AppendUnknown(absl::string_view key, Slice value) {
1097
+ unknown_.EmplaceBack(Slice::FromCopiedString(key), value.Ref());
927
1098
  }
928
- GRPC_MDELEM_UNREF(old_mdelem);
929
- AssertValidCallouts();
930
- return error;
931
- }
932
1099
 
933
- template <typename... Traits>
934
- void MetadataMap<Traits...>::Clear() {
935
- // TODO(ctiller): implement this without deconstructing/reconstructing once
936
- // linked_mdelem is no longer a thing.
937
- auto* arena = elem_storage_.arena();
938
- this->~MetadataMap();
939
- new (this) MetadataMap(arena);
940
- }
941
-
942
- template <typename... Traits>
943
- size_t MetadataMap<Traits...>::TransportSize() const {
944
- size_t size = 0;
945
- for (grpc_linked_mdelem* elem = list_.head; elem != nullptr;
946
- elem = elem->next) {
947
- size += GRPC_MDELEM_LENGTH(elem->md);
1100
+ void RemoveUnknown(absl::string_view key) {
1101
+ unknown_.SetEnd(std::remove_if(unknown_.begin(), unknown_.end(),
1102
+ [key](const std::pair<Slice, Slice>& p) {
1103
+ return p.first.as_string_view() == key;
1104
+ }));
948
1105
  }
949
- return size;
950
- }
951
1106
 
952
- template <typename... Traits>
953
- bool MetadataMap<Traits...>::ReplaceIfExists(grpc_slice key, grpc_slice value) {
954
- AssertValidCallouts();
955
- for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) {
956
- if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) {
957
- auto new_mdelem = grpc_mdelem_from_slices(key, value);
958
- GRPC_MDELEM_UNREF(l->md);
959
- l->md = new_mdelem;
960
- AssertValidCallouts();
961
- return true;
1107
+ absl::optional<absl::string_view> GetStringValueUnknown(
1108
+ absl::string_view key, std::string* backing) const {
1109
+ absl::optional<absl::string_view> out;
1110
+ for (const auto& p : unknown_) {
1111
+ if (p.first.as_string_view() == key) {
1112
+ if (!out.has_value()) {
1113
+ out = p.second.as_string_view();
1114
+ } else {
1115
+ out = *backing = absl::StrCat(*out, ",", p.second.as_string_view());
1116
+ }
1117
+ }
962
1118
  }
1119
+ return out;
963
1120
  }
964
- AssertValidCallouts();
965
- return false;
966
- }
967
-
968
- } // namespace grpc_core
969
-
970
- using grpc_metadata_batch = grpc_core::MetadataMap<
971
- grpc_core::GrpcTimeoutMetadata, grpc_core::TeMetadata,
972
- grpc_core::UserAgentMetadata, grpc_core::GrpcMessageMetadata,
973
- grpc_core::HostMetadata, grpc_core::XEndpointLoadMetricsBinMetadata,
974
- grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata,
975
- grpc_core::GrpcTagsBinMetadata>;
976
-
977
- inline void grpc_metadata_batch_clear(grpc_metadata_batch* batch) {
978
- batch->Clear();
979
- }
980
- inline bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch) {
981
- return batch->empty();
982
- }
983
-
984
- /* Returns the transport size of the batch. */
985
- inline size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) {
986
- return batch->TransportSize();
987
- }
988
1121
 
989
- /** Remove \a storage from the batch, unreffing the mdelem contained */
990
- inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
991
- grpc_linked_mdelem* storage) {
992
- batch->Remove(storage);
993
- }
994
- inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
995
- grpc_metadata_batch_callouts_index idx) {
996
- batch->Remove(idx);
997
- }
998
-
999
- /** Substitute a new mdelem for an old value */
1000
- inline grpc_error_handle grpc_metadata_batch_substitute(
1001
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1002
- grpc_mdelem new_mdelem) {
1003
- return batch->Substitute(storage, new_mdelem);
1004
- }
1005
-
1006
- void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage,
1007
- const grpc_slice& value);
1008
-
1009
- /** Returns metadata value(s) for the specified key.
1010
- If the key is not present in the batch, returns absl::nullopt.
1011
- If the key is present exactly once in the batch, returns a string_view of
1012
- that value.
1013
- If the key is present more than once in the batch, constructs a
1014
- comma-concatenated string of all values in concatenated_value and returns a
1015
- string_view of that string. */
1016
- inline absl::optional<absl::string_view> grpc_metadata_batch_get_value(
1017
- grpc_metadata_batch* batch, absl::string_view target_key,
1018
- std::string* concatenated_value) {
1019
- return batch->GetValue(target_key, concatenated_value);
1020
- }
1021
-
1022
- /** Add \a storage to the beginning of \a batch. storage->md is
1023
- assumed to be valid.
1024
- \a storage is owned by the caller and must survive for the
1025
- lifetime of batch. This usually means it should be around
1026
- for the lifetime of the call. */
1027
- inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head(
1028
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage) {
1029
- return batch->LinkHead(storage);
1030
- }
1122
+ // Table of known metadata types.
1123
+ Table<Value<Traits>...> table_;
1124
+ // Backing store for added metadata.
1125
+ ChunkedVector<std::pair<Slice, Slice>, 10> unknown_;
1126
+ };
1031
1127
 
1032
- inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head(
1033
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1034
- grpc_metadata_batch_callouts_index idx) {
1035
- return batch->LinkHead(storage, idx);
1128
+ // Ok/not-ok check for metadata maps that contain GrpcStatusMetadata, so that
1129
+ // they can be used as result types for TrySeq.
1130
+ template <typename Derived, typename... Args>
1131
+ inline bool IsStatusOk(const MetadataMap<Derived, Args...>& m) {
1132
+ return m.get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
1133
+ GRPC_STATUS_OK;
1036
1134
  }
1037
1135
 
1038
- /** Add \a storage to the end of \a batch. storage->md is
1039
- assumed to be valid.
1040
- \a storage is owned by the caller and must survive for the
1041
- lifetime of batch. This usually means it should be around
1042
- for the lifetime of the call. */
1043
- inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail(
1044
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage) {
1045
- return batch->LinkTail(storage);
1046
- }
1136
+ template <typename Derived, typename... Traits>
1137
+ MetadataMap<Derived, Traits...>::MetadataMap(Arena* arena) : unknown_(arena) {}
1047
1138
 
1048
- inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail(
1049
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1050
- grpc_metadata_batch_callouts_index idx) {
1051
- return batch->LinkTail(storage, idx);
1052
- }
1139
+ template <typename Derived, typename... Traits>
1140
+ MetadataMap<Derived, Traits...>::MetadataMap(MetadataMap&& other) noexcept
1141
+ : table_(std::move(other.table_)), unknown_(std::move(other.unknown_)) {}
1053
1142
 
1054
- /** Add \a elem_to_add as the first element in \a batch, using
1055
- \a storage as backing storage for the linked list element.
1056
- \a storage is owned by the caller and must survive for the
1057
- lifetime of batch. This usually means it should be around
1058
- for the lifetime of the call.
1059
- Takes ownership of \a elem_to_add */
1060
- inline grpc_error_handle grpc_metadata_batch_add_head(
1061
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1062
- grpc_mdelem elem_to_add) {
1063
- return batch->AddHead(storage, elem_to_add);
1143
+ // We never create MetadataMap directly, instead we create Derived, but we want
1144
+ // to be able to move it without redeclaring this.
1145
+ // NOLINTNEXTLINE(misc-unconventional-assign-operator)
1146
+ template <typename Derived, typename... Traits>
1147
+ Derived& MetadataMap<Derived, Traits...>::operator=(
1148
+ MetadataMap&& other) noexcept {
1149
+ table_ = std::move(other.table_);
1150
+ unknown_ = std::move(other.unknown_);
1151
+ return static_cast<Derived&>(*this);
1064
1152
  }
1065
1153
 
1066
- // TODO(arjunroy, roth): Remove redundant methods.
1067
- // add/link_head/tail are almost identical.
1068
- inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head(
1069
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1070
- grpc_metadata_batch_callouts_index idx) {
1071
- return grpc_metadata_batch_link_head(batch, storage, idx);
1072
- }
1154
+ template <typename Derived, typename... Traits>
1155
+ MetadataMap<Derived, Traits...>::~MetadataMap() = default;
1073
1156
 
1074
- inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head(
1075
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1076
- grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) {
1077
- GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
1078
- storage->md = elem_to_add;
1079
- return grpc_metadata_batch_add_head(batch, storage, idx);
1157
+ template <typename Derived, typename... Traits>
1158
+ void MetadataMap<Derived, Traits...>::Clear() {
1159
+ table_.ClearAll();
1160
+ unknown_.Clear();
1080
1161
  }
1081
1162
 
1082
- /** Add \a elem_to_add as the last element in \a batch, using
1083
- \a storage as backing storage for the linked list element.
1084
- \a storage is owned by the caller and must survive for the
1085
- lifetime of batch. This usually means it should be around
1086
- for the lifetime of the call.
1087
- Takes ownership of \a elem_to_add */
1088
- inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_add_tail(
1089
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1090
- grpc_mdelem elem_to_add) {
1091
- return batch->AddTail(storage, elem_to_add);
1163
+ template <typename Derived, typename... Traits>
1164
+ size_t MetadataMap<Derived, Traits...>::TransportSize() const {
1165
+ TransportSizeEncoder enc;
1166
+ Encode(&enc);
1167
+ return enc.size();
1092
1168
  }
1093
1169
 
1094
- inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
1095
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1096
- grpc_metadata_batch_callouts_index idx) {
1097
- return grpc_metadata_batch_link_tail(batch, storage, idx);
1170
+ template <typename Derived, typename... Traits>
1171
+ Derived MetadataMap<Derived, Traits...>::Copy() const {
1172
+ Derived out(unknown_.arena());
1173
+ metadata_detail::CopySink<Derived> sink(&out);
1174
+ Encode(&sink);
1175
+ return out;
1098
1176
  }
1099
1177
 
1100
- inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
1101
- grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
1102
- grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) {
1103
- GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
1104
- storage->md = elem_to_add;
1105
- return grpc_metadata_batch_add_tail(batch, storage, idx);
1178
+ template <typename Derived, typename... Traits>
1179
+ void MetadataMap<Derived, Traits...>::Log(
1180
+ absl::FunctionRef<void(absl::string_view, absl::string_view)> log_fn)
1181
+ const {
1182
+ LogEncoder enc(log_fn);
1183
+ Encode(&enc);
1106
1184
  }
1107
1185
 
1108
- typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)(
1109
- void* user_data, grpc_mdelem elem);
1110
- inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_filter(
1111
- grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func,
1112
- void* user_data, const char* composite_error_string) {
1113
- return batch->Filter([=](grpc_mdelem elem) { return func(user_data, elem); },
1114
- composite_error_string);
1115
- }
1186
+ } // namespace grpc_core
1116
1187
 
1117
- inline void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch) {
1118
- batch->AssertOk();
1119
- }
1188
+ struct grpc_metadata_batch;
1189
+
1190
+ using grpc_metadata_batch_base = grpc_core::MetadataMap<
1191
+ grpc_metadata_batch,
1192
+ // Colon prefixed headers first
1193
+ grpc_core::HttpPathMetadata, grpc_core::HttpAuthorityMetadata,
1194
+ grpc_core::HttpMethodMetadata, grpc_core::HttpStatusMetadata,
1195
+ grpc_core::HttpSchemeMetadata,
1196
+ // Non-colon prefixed headers begin here
1197
+ grpc_core::ContentTypeMetadata, grpc_core::TeMetadata,
1198
+ grpc_core::GrpcEncodingMetadata, grpc_core::GrpcInternalEncodingRequest,
1199
+ grpc_core::GrpcAcceptEncodingMetadata, grpc_core::GrpcStatusMetadata,
1200
+ grpc_core::GrpcTimeoutMetadata, grpc_core::GrpcPreviousRpcAttemptsMetadata,
1201
+ grpc_core::GrpcRetryPushbackMsMetadata, grpc_core::UserAgentMetadata,
1202
+ grpc_core::GrpcMessageMetadata, grpc_core::HostMetadata,
1203
+ grpc_core::XEndpointLoadMetricsBinMetadata,
1204
+ grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata,
1205
+ grpc_core::GrpcTagsBinMetadata, grpc_core::GrpcLbClientStatsMetadata,
1206
+ grpc_core::LbCostBinMetadata, grpc_core::LbTokenMetadata>;
1120
1207
 
1121
- /// Copies \a src to \a dst.
1122
- ///
1123
- /// For each mdelem in \a src, if the mdelem is of storage types
1124
- /// GRPC_MDELEM_STORAGE_INTERNED or GRPC_MDELEM_STORAGE_ALLOCATED,
1125
- /// refs the original mdelem for the copy. Otherwise, makes a new
1126
- /// mdelem that will hold its own refs to the key and value slices.
1127
- void grpc_metadata_batch_copy(const grpc_metadata_batch* src,
1128
- grpc_metadata_batch* dst);
1208
+ struct grpc_metadata_batch : public grpc_metadata_batch_base {
1209
+ using grpc_metadata_batch_base::grpc_metadata_batch_base;
1210
+ };
1129
1211
 
1130
1212
  #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */