grpc 1.35.0.pre1 → 1.37.1

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 (507) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +121 -89
  3. data/include/grpc/grpc.h +15 -1
  4. data/include/grpc/grpc_security.h +16 -11
  5. data/include/grpc/impl/codegen/port_platform.h +2 -0
  6. data/src/core/ext/filters/client_channel/client_channel.cc +359 -331
  7. data/src/core/ext/filters/client_channel/client_channel.h +0 -2
  8. data/src/core/ext/filters/client_channel/client_channel_factory.h +2 -1
  9. data/src/core/ext/filters/client_channel/config_selector.h +9 -1
  10. data/src/core/ext/filters/client_channel/dynamic_filters.cc +9 -4
  11. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +24 -142
  12. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +15 -10
  13. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +2 -2
  14. data/src/core/ext/filters/client_channel/lb_policy.cc +3 -0
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +3 -5
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +1 -2
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +1 -2
  18. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +1 -1
  19. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +8 -6
  20. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +23 -0
  21. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +27 -0
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +289 -170
  23. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h +5 -0
  24. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +8 -25
  25. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +1 -1
  26. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +232 -110
  27. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +27 -67
  28. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +10 -9
  29. data/src/core/ext/filters/client_channel/resolver.cc +5 -5
  30. data/src/core/ext/filters/client_channel/resolver.h +1 -12
  31. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +36 -45
  32. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +2 -2
  33. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +3 -1
  34. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +34 -50
  35. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +16 -14
  36. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +18 -15
  37. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +377 -0
  38. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +4 -4
  39. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +307 -155
  40. data/src/core/ext/filters/client_channel/server_address.cc +9 -0
  41. data/src/core/ext/filters/client_channel/server_address.h +31 -0
  42. data/src/core/ext/filters/client_channel/subchannel.cc +69 -146
  43. data/src/core/ext/filters/client_channel/subchannel.h +63 -95
  44. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +16 -2
  45. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +10 -8
  46. data/src/core/ext/filters/client_idle/client_idle_filter.cc +1 -1
  47. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +500 -0
  48. data/src/core/ext/filters/fault_injection/fault_injection_filter.h +39 -0
  49. data/src/core/ext/filters/fault_injection/service_config_parser.cc +189 -0
  50. data/src/core/ext/filters/fault_injection/service_config_parser.h +85 -0
  51. data/src/core/ext/filters/max_age/max_age_filter.cc +35 -32
  52. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc +1 -1
  53. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +2 -2
  54. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +3 -2
  55. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +1 -1
  56. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +3 -2
  57. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +490 -178
  58. data/src/core/ext/transport/chttp2/server/chttp2_server.h +11 -2
  59. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc +11 -1
  60. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +1 -1
  61. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc +62 -18
  62. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +39 -7
  63. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +12 -1
  64. data/src/core/ext/transport/chttp2/transport/frame_data.cc +5 -1
  65. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +1 -1
  66. data/src/core/ext/transport/chttp2/transport/internal.h +1 -0
  67. data/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c +406 -0
  68. data/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h +1459 -0
  69. data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c +0 -1
  70. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c +350 -0
  71. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h +1348 -0
  72. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c +11 -16
  73. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h +42 -59
  74. data/src/core/ext/upb-generated/envoy/config/cluster/v3/outlier_detection.upb.c +3 -2
  75. data/src/core/ext/upb-generated/envoy/config/cluster/v3/outlier_detection.upb.h +15 -0
  76. data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.c +25 -1
  77. data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.h +75 -0
  78. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.c +2 -2
  79. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.h +9 -9
  80. data/src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.c +7 -7
  81. data/src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.h +28 -13
  82. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +6 -0
  83. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +25 -0
  84. data/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c +0 -1
  85. data/src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.c +11 -5
  86. data/src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.h +41 -7
  87. data/src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint.upb.c +0 -1
  88. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c +23 -21
  89. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h +122 -77
  90. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c +13 -9
  91. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h +37 -5
  92. data/src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c +0 -1
  93. data/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c +144 -0
  94. data/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h +488 -0
  95. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c +141 -0
  96. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h +452 -0
  97. data/src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c +11 -9
  98. data/src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h +44 -27
  99. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c +57 -16
  100. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h +150 -0
  101. data/src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c +0 -1
  102. data/src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c +29 -0
  103. data/src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h +67 -0
  104. data/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c +79 -0
  105. data/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h +268 -0
  106. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c +78 -0
  107. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h +281 -0
  108. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c +41 -0
  109. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h +113 -0
  110. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +19 -21
  111. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +64 -51
  112. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c +0 -1
  113. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c +16 -13
  114. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h +50 -18
  115. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c +4 -7
  116. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h +0 -17
  117. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.c +0 -1
  118. data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.c +30 -23
  119. data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.h +85 -73
  120. data/src/core/ext/upb-generated/envoy/service/endpoint/v3/eds.upb.c +0 -3
  121. data/src/core/ext/upb-generated/envoy/service/listener/v3/lds.upb.c +0 -3
  122. data/src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c +0 -1
  123. data/src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c +0 -2
  124. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c +93 -0
  125. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h +323 -0
  126. data/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c +36 -0
  127. data/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h +90 -0
  128. data/src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c +0 -1
  129. data/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c +46 -0
  130. data/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h +124 -0
  131. data/src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c +21 -4
  132. data/src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h +29 -0
  133. data/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c +33 -0
  134. data/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h +77 -0
  135. data/src/core/ext/upb-generated/{udpa/core/v1 → xds/core/v3}/authority.upb.c +5 -5
  136. data/src/core/ext/upb-generated/xds/core/v3/authority.upb.h +60 -0
  137. data/src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c +52 -0
  138. data/src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h +143 -0
  139. data/src/core/ext/upb-generated/xds/core/v3/context_params.upb.c +42 -0
  140. data/src/core/ext/upb-generated/xds/core/v3/context_params.upb.h +84 -0
  141. data/src/core/ext/upb-generated/{udpa/core/v1 → xds/core/v3}/resource.upb.c +9 -9
  142. data/src/core/ext/upb-generated/xds/core/v3/resource.upb.h +94 -0
  143. data/src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c +54 -0
  144. data/src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h +166 -0
  145. data/src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c +36 -0
  146. data/src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h +85 -0
  147. data/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c +354 -0
  148. data/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h +140 -0
  149. data/src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c +168 -171
  150. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c +383 -0
  151. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h +115 -0
  152. data/src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c +405 -420
  153. data/src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.h +2 -2
  154. data/src/core/ext/upbdefs-generated/envoy/config/cluster/v3/outlier_detection.upbdefs.c +12 -9
  155. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/base.upbdefs.c +177 -171
  156. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/base.upbdefs.h +10 -0
  157. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/config_source.upbdefs.c +88 -88
  158. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/health_check.upbdefs.c +153 -153
  159. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c +10 -7
  160. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.h +5 -0
  161. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.c +4 -7
  162. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/substitution_format_string.upbdefs.c +33 -20
  163. data/src/core/ext/upbdefs-generated/envoy/config/endpoint/v3/endpoint.upbdefs.c +56 -59
  164. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c +116 -111
  165. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c +129 -121
  166. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c +21 -24
  167. data/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c +141 -0
  168. data/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h +70 -0
  169. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c +141 -0
  170. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h +70 -0
  171. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c +17 -13
  172. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c +753 -724
  173. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h +10 -0
  174. data/src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c +22 -25
  175. data/src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c +51 -0
  176. data/src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h +35 -0
  177. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c +102 -0
  178. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h +55 -0
  179. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c +120 -0
  180. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h +45 -0
  181. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c +76 -0
  182. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h +35 -0
  183. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c +371 -377
  184. data/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c +12 -16
  185. data/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c +112 -108
  186. data/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/secret.upbdefs.c +45 -53
  187. data/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c +177 -180
  188. data/src/core/ext/upbdefs-generated/envoy/service/discovery/v3/discovery.upbdefs.c +92 -102
  189. data/src/core/ext/upbdefs-generated/envoy/service/discovery/v3/discovery.upbdefs.h +5 -0
  190. data/src/core/ext/upbdefs-generated/envoy/service/endpoint/v3/eds.upbdefs.c +32 -42
  191. data/src/core/ext/upbdefs-generated/envoy/service/listener/v3/lds.upbdefs.c +30 -40
  192. data/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c +4 -7
  193. data/src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c +38 -44
  194. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c +130 -0
  195. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h +50 -0
  196. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c +56 -0
  197. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h +35 -0
  198. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c +30 -33
  199. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c +63 -0
  200. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h +40 -0
  201. data/src/core/ext/upbdefs-generated/google/protobuf/any.upbdefs.c +8 -7
  202. data/src/core/ext/upbdefs-generated/google/protobuf/descriptor.upbdefs.c +9 -9
  203. data/src/core/ext/upbdefs-generated/google/protobuf/duration.upbdefs.c +9 -8
  204. data/src/core/ext/upbdefs-generated/google/protobuf/empty.upbdefs.c +8 -8
  205. data/src/core/ext/upbdefs-generated/google/protobuf/struct.upbdefs.c +8 -8
  206. data/src/core/ext/upbdefs-generated/google/protobuf/timestamp.upbdefs.c +9 -8
  207. data/src/core/ext/upbdefs-generated/google/protobuf/wrappers.upbdefs.c +8 -8
  208. data/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c +44 -0
  209. data/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h +35 -0
  210. data/src/core/ext/upbdefs-generated/validate/validate.upbdefs.c +14 -11
  211. data/src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c +42 -0
  212. data/src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h +35 -0
  213. data/src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c +62 -0
  214. data/src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h +40 -0
  215. data/src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.c +45 -0
  216. data/src/core/ext/upbdefs-generated/xds/core/v3/context_params.upbdefs.h +40 -0
  217. data/src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.c +49 -0
  218. data/src/core/ext/upbdefs-generated/xds/core/v3/resource.upbdefs.h +35 -0
  219. data/src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.c +67 -0
  220. data/src/core/ext/upbdefs-generated/xds/core/v3/resource_locator.upbdefs.h +40 -0
  221. data/src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.c +50 -0
  222. data/src/core/ext/upbdefs-generated/xds/core/v3/resource_name.upbdefs.h +35 -0
  223. data/src/core/ext/xds/xds_api.cc +2149 -666
  224. data/src/core/ext/xds/xds_api.h +321 -119
  225. data/src/core/ext/xds/xds_bootstrap.cc +80 -45
  226. data/src/core/ext/xds/xds_bootstrap.h +17 -5
  227. data/src/core/ext/xds/xds_certificate_provider.cc +180 -74
  228. data/src/core/ext/xds/xds_certificate_provider.h +83 -44
  229. data/src/core/ext/xds/xds_client.cc +181 -34
  230. data/src/core/ext/xds/xds_client.h +29 -0
  231. data/src/core/ext/xds/xds_client_stats.cc +2 -1
  232. data/src/core/ext/xds/xds_client_stats.h +2 -2
  233. data/src/core/ext/xds/xds_http_fault_filter.cc +226 -0
  234. data/src/core/ext/xds/xds_http_fault_filter.h +63 -0
  235. data/src/core/ext/xds/xds_http_filters.cc +114 -0
  236. data/src/core/ext/xds/xds_http_filters.h +130 -0
  237. data/src/core/ext/xds/xds_server_config_fetcher.cc +425 -24
  238. data/src/core/lib/channel/channel_stack.cc +12 -0
  239. data/src/core/lib/channel/channel_stack.h +7 -0
  240. data/src/core/lib/channel/channelz.cc +92 -4
  241. data/src/core/lib/channel/channelz.h +30 -1
  242. data/src/core/lib/channel/channelz_registry.cc +14 -0
  243. data/src/core/lib/channel/handshaker.cc +2 -44
  244. data/src/core/lib/channel/handshaker.h +1 -18
  245. data/src/core/lib/channel/status_util.cc +12 -2
  246. data/src/core/lib/channel/status_util.h +5 -0
  247. data/src/core/lib/gpr/log.cc +6 -1
  248. data/src/core/lib/gpr/sync_abseil.cc +3 -6
  249. data/src/core/lib/gpr/sync_windows.cc +2 -2
  250. data/src/core/lib/gprpp/atomic.h +3 -3
  251. data/src/core/lib/gprpp/dual_ref_counted.h +3 -3
  252. data/src/core/lib/gprpp/mpscq.cc +2 -2
  253. data/src/core/lib/gprpp/ref_counted.h +1 -1
  254. data/src/core/lib/gprpp/ref_counted_ptr.h +2 -0
  255. data/src/core/lib/gprpp/sync.h +129 -40
  256. data/src/core/lib/gprpp/thd.h +1 -1
  257. data/src/core/lib/gprpp/time_util.cc +77 -0
  258. data/src/core/lib/gprpp/time_util.h +42 -0
  259. data/src/core/lib/http/httpcli_security_connector.cc +2 -2
  260. data/src/core/lib/iomgr/buffer_list.h +1 -1
  261. data/src/core/lib/iomgr/cfstream_handle.cc +2 -2
  262. data/src/core/lib/iomgr/error.h +1 -1
  263. data/src/core/lib/iomgr/ev_apple.cc +11 -8
  264. data/src/core/lib/iomgr/ev_epoll1_linux.cc +3 -3
  265. data/src/core/lib/iomgr/ev_epollex_linux.cc +4 -4
  266. data/src/core/lib/iomgr/ev_posix.cc +3 -3
  267. data/src/core/lib/iomgr/exec_ctx.cc +6 -2
  268. data/src/core/lib/iomgr/iomgr_posix.cc +0 -1
  269. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +0 -1
  270. data/src/core/lib/iomgr/resource_quota.cc +1 -1
  271. data/src/core/lib/iomgr/sockaddr_utils.cc +121 -1
  272. data/src/core/lib/iomgr/sockaddr_utils.h +25 -0
  273. data/src/core/lib/iomgr/socket_utils_common_posix.cc +1 -0
  274. data/src/core/lib/iomgr/tcp_client_posix.cc +1 -1
  275. data/src/core/lib/iomgr/tcp_posix.cc +5 -8
  276. data/src/core/lib/iomgr/tcp_uv.cc +2 -2
  277. data/src/core/lib/iomgr/timer_generic.cc +2 -2
  278. data/src/core/lib/iomgr/timer_manager.cc +1 -1
  279. data/src/core/lib/iomgr/wakeup_fd_nospecial.cc +1 -1
  280. data/src/core/lib/matchers/matchers.cc +339 -0
  281. data/src/core/lib/matchers/matchers.h +160 -0
  282. data/src/core/lib/security/credentials/alts/alts_credentials.cc +2 -1
  283. data/src/core/lib/security/credentials/alts/alts_credentials.h +1 -1
  284. data/src/core/lib/security/credentials/credentials.h +2 -1
  285. data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +1 -1
  286. data/src/core/lib/security/credentials/external/external_account_credentials.cc +2 -2
  287. data/src/core/lib/security/credentials/external/file_external_account_credentials.cc +1 -1
  288. data/src/core/lib/security/credentials/external/url_external_account_credentials.cc +1 -1
  289. data/src/core/lib/security/credentials/fake/fake_credentials.cc +1 -1
  290. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +7 -6
  291. data/src/core/lib/security/credentials/insecure/insecure_credentials.cc +2 -2
  292. data/src/core/lib/security/credentials/jwt/json_token.cc +0 -3
  293. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +0 -3
  294. data/src/core/lib/security/credentials/local/local_credentials.cc +2 -1
  295. data/src/core/lib/security/credentials/local/local_credentials.h +1 -1
  296. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +2 -1
  297. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +1 -1
  298. data/src/core/lib/security/credentials/tls/tls_credentials.cc +2 -1
  299. data/src/core/lib/security/credentials/tls/tls_credentials.h +1 -1
  300. data/src/core/lib/security/credentials/xds/xds_credentials.cc +128 -59
  301. data/src/core/lib/security/credentials/xds/xds_credentials.h +3 -3
  302. data/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc +5 -5
  303. data/src/core/lib/security/security_connector/ssl_utils.cc +9 -4
  304. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +32 -14
  305. data/src/core/lib/security/transport/security_handshaker.cc +33 -5
  306. data/src/core/lib/security/transport/server_auth_filter.cc +7 -0
  307. data/src/core/lib/slice/slice_intern.cc +5 -6
  308. data/src/core/lib/surface/channel.h +3 -3
  309. data/src/core/lib/surface/completion_queue.cc +1 -1
  310. data/src/core/lib/surface/init.cc +13 -15
  311. data/src/core/lib/surface/lame_client.cc +38 -19
  312. data/src/core/lib/surface/lame_client.h +4 -3
  313. data/src/core/lib/surface/server.cc +43 -36
  314. data/src/core/lib/surface/server.h +76 -14
  315. data/src/core/lib/surface/version.cc +2 -2
  316. data/src/core/lib/transport/metadata.cc +6 -2
  317. data/src/core/lib/transport/metadata_batch.cc +27 -0
  318. data/src/core/lib/transport/metadata_batch.h +14 -0
  319. data/src/core/plugin_registry/grpc_plugin_registry.cc +12 -0
  320. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +18 -24
  321. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +16 -21
  322. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +1 -1
  323. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +1 -3
  324. data/src/core/tsi/fake_transport_security.cc +11 -2
  325. data/src/core/tsi/ssl/session_cache/ssl_session.h +0 -3
  326. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +0 -2
  327. data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +2 -4
  328. data/src/core/tsi/ssl_transport_security.cc +0 -3
  329. data/src/core/tsi/ssl_transport_security.h +0 -3
  330. data/src/ruby/ext/grpc/extconf.rb +9 -1
  331. data/src/ruby/ext/grpc/rb_channel.c +10 -1
  332. data/src/ruby/ext/grpc/rb_channel_credentials.c +11 -1
  333. data/src/ruby/ext/grpc/rb_channel_credentials.h +4 -0
  334. data/src/ruby/ext/grpc/rb_compression_options.c +1 -1
  335. data/src/ruby/ext/grpc/rb_enable_cpp.cc +1 -1
  336. data/src/ruby/ext/grpc/rb_grpc.c +4 -0
  337. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  338. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  339. data/src/ruby/ext/grpc/rb_server.c +13 -1
  340. data/src/ruby/ext/grpc/rb_server_credentials.c +19 -3
  341. data/src/ruby/ext/grpc/rb_server_credentials.h +4 -0
  342. data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +215 -0
  343. data/src/ruby/ext/grpc/rb_xds_channel_credentials.h +35 -0
  344. data/src/ruby/ext/grpc/rb_xds_server_credentials.c +169 -0
  345. data/src/ruby/ext/grpc/rb_xds_server_credentials.h +35 -0
  346. data/src/ruby/lib/grpc/generic/client_stub.rb +4 -2
  347. data/src/ruby/lib/grpc/version.rb +1 -1
  348. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +7 -0
  349. data/src/ruby/spec/call_spec.rb +1 -1
  350. data/src/ruby/spec/channel_credentials_spec.rb +32 -0
  351. data/src/ruby/spec/channel_spec.rb +17 -6
  352. data/src/ruby/spec/client_auth_spec.rb +27 -1
  353. data/src/ruby/spec/errors_spec.rb +1 -1
  354. data/src/ruby/spec/generic/active_call_spec.rb +2 -2
  355. data/src/ruby/spec/generic/client_stub_spec.rb +4 -4
  356. data/src/ruby/spec/generic/rpc_server_spec.rb +1 -1
  357. data/src/ruby/spec/server_credentials_spec.rb +25 -0
  358. data/src/ruby/spec/server_spec.rb +22 -0
  359. data/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc +1 -0
  360. data/third_party/boringssl-with-bazel/err_data.c +715 -713
  361. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_bitstr.c +3 -3
  362. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_enum.c +2 -2
  363. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_int.c +5 -5
  364. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_object.c +3 -10
  365. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_octet.c +3 -3
  366. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_type.c +4 -2
  367. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_utctm.c +2 -2
  368. data/third_party/boringssl-with-bazel/src/crypto/asn1/asn1_lib.c +15 -14
  369. data/third_party/boringssl-with-bazel/src/crypto/asn1/asn1_locl.h +30 -0
  370. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_dec.c +28 -79
  371. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_enc.c +39 -85
  372. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_fre.c +5 -16
  373. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_new.c +10 -61
  374. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_typ.c +0 -2
  375. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_utl.c +2 -2
  376. data/third_party/boringssl-with-bazel/src/crypto/bio/socket_helper.c +4 -0
  377. data/third_party/boringssl-with-bazel/src/crypto/blake2/blake2.c +158 -0
  378. data/third_party/boringssl-with-bazel/src/crypto/bn_extra/bn_asn1.c +3 -10
  379. data/third_party/boringssl-with-bazel/src/crypto/bytestring/ber.c +8 -9
  380. data/third_party/boringssl-with-bazel/src/crypto/bytestring/cbs.c +60 -45
  381. data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_chacha20poly1305.c +6 -81
  382. data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/internal.h +87 -0
  383. data/third_party/boringssl-with-bazel/src/crypto/cpu-aarch64-win.c +41 -0
  384. data/third_party/boringssl-with-bazel/src/crypto/cpu-arm-linux.c +11 -2
  385. data/third_party/boringssl-with-bazel/src/crypto/cpu-arm.c +3 -3
  386. data/third_party/boringssl-with-bazel/src/crypto/{dh → dh_extra}/dh_asn1.c +0 -0
  387. data/third_party/boringssl-with-bazel/src/crypto/{dh → dh_extra}/params.c +179 -0
  388. data/third_party/boringssl-with-bazel/src/crypto/digest_extra/digest_extra.c +25 -0
  389. data/third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c +2 -17
  390. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c +3 -1
  391. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/bn.c +13 -20
  392. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/div.c +2 -3
  393. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/internal.h +9 -1
  394. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/cipher/cipher.c +21 -13
  395. data/third_party/boringssl-with-bazel/src/crypto/{dh → fipsmodule/dh}/check.c +0 -0
  396. data/third_party/boringssl-with-bazel/src/crypto/{dh → fipsmodule/dh}/dh.c +136 -213
  397. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec.c +12 -0
  398. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_key.c +9 -1
  399. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h +28 -0
  400. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c +135 -43
  401. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c +0 -7
  402. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +51 -32
  403. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/self_check/self_check.c +147 -0
  404. data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +18 -29
  405. data/third_party/boringssl-with-bazel/src/crypto/hpke/internal.h +13 -4
  406. data/third_party/boringssl-with-bazel/src/crypto/poly1305/poly1305.c +10 -7
  407. data/third_party/boringssl-with-bazel/src/crypto/poly1305/poly1305_arm.c +13 -11
  408. data/third_party/boringssl-with-bazel/src/crypto/poly1305/poly1305_vec.c +4 -0
  409. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/passive.c +34 -0
  410. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/rand_extra.c +4 -0
  411. data/third_party/boringssl-with-bazel/src/crypto/stack/stack.c +7 -13
  412. data/third_party/boringssl-with-bazel/src/crypto/x509/rsa_pss.c +5 -1
  413. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c +1 -29
  414. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c +10 -7
  415. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_r2x.c +1 -1
  416. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c +8 -8
  417. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_v3.c +1 -1
  418. data/third_party/boringssl-with-bazel/src/crypto/x509/x509cset.c +29 -23
  419. data/third_party/boringssl-with-bazel/src/crypto/x509/x_attrib.c +22 -17
  420. data/third_party/boringssl-with-bazel/src/crypto/x509/x_crl.c +1 -2
  421. data/third_party/boringssl-with-bazel/src/crypto/x509/x_pkey.c +2 -2
  422. data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509.c +39 -4
  423. data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509a.c +2 -2
  424. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_akey.c +3 -3
  425. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_alt.c +11 -10
  426. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_bitst.c +3 -3
  427. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_conf.c +25 -25
  428. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_cpols.c +2 -2
  429. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_enum.c +2 -1
  430. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_genn.c +40 -20
  431. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_ia5.c +3 -4
  432. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_lib.c +25 -36
  433. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_prn.c +1 -1
  434. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_skey.c +6 -6
  435. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_utl.c +6 -6
  436. data/third_party/boringssl-with-bazel/src/include/openssl/arm_arch.h +3 -3
  437. data/third_party/boringssl-with-bazel/src/include/openssl/asn1.h +652 -545
  438. data/third_party/boringssl-with-bazel/src/include/openssl/asn1t.h +0 -167
  439. data/third_party/boringssl-with-bazel/src/include/openssl/base.h +10 -5
  440. data/third_party/boringssl-with-bazel/src/include/openssl/blake2.h +62 -0
  441. data/third_party/boringssl-with-bazel/src/include/openssl/bytestring.h +22 -7
  442. data/third_party/boringssl-with-bazel/src/include/openssl/cipher.h +19 -0
  443. data/third_party/boringssl-with-bazel/src/include/openssl/cpu.h +22 -32
  444. data/third_party/boringssl-with-bazel/src/include/openssl/dh.h +56 -26
  445. data/third_party/boringssl-with-bazel/src/include/openssl/digest.h +1 -0
  446. data/third_party/boringssl-with-bazel/src/include/openssl/ec.h +15 -0
  447. data/third_party/boringssl-with-bazel/src/include/openssl/evp.h +12 -2
  448. data/third_party/boringssl-with-bazel/src/include/openssl/rand.h +3 -0
  449. data/third_party/boringssl-with-bazel/src/include/openssl/span.h +2 -1
  450. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +67 -33
  451. data/third_party/boringssl-with-bazel/src/include/openssl/tls1.h +27 -8
  452. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +287 -99
  453. data/third_party/boringssl-with-bazel/src/include/openssl/x509v3.h +139 -36
  454. data/third_party/boringssl-with-bazel/src/ssl/handshake.cc +4 -3
  455. data/third_party/boringssl-with-bazel/src/ssl/handshake_client.cc +11 -20
  456. data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +10 -5
  457. data/third_party/boringssl-with-bazel/src/ssl/internal.h +37 -16
  458. data/third_party/boringssl-with-bazel/src/ssl/s3_lib.cc +0 -1
  459. data/third_party/boringssl-with-bazel/src/ssl/ssl_asn1.cc +7 -8
  460. data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +20 -14
  461. data/third_party/boringssl-with-bazel/src/ssl/ssl_session.cc +7 -8
  462. data/third_party/boringssl-with-bazel/src/ssl/ssl_transcript.cc +2 -2
  463. data/third_party/boringssl-with-bazel/src/ssl/t1_enc.cc +5 -7
  464. data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +362 -50
  465. data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +2 -2
  466. data/third_party/boringssl-with-bazel/src/ssl/tls13_enc.cc +48 -15
  467. data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +66 -24
  468. data/third_party/xxhash/xxhash.h +5443 -0
  469. metadata +140 -84
  470. data/src/core/ext/upb-generated/udpa/core/v1/authority.upb.h +0 -60
  471. data/src/core/ext/upb-generated/udpa/core/v1/collection_entry.upb.c +0 -52
  472. data/src/core/ext/upb-generated/udpa/core/v1/collection_entry.upb.h +0 -143
  473. data/src/core/ext/upb-generated/udpa/core/v1/context_params.upb.c +0 -42
  474. data/src/core/ext/upb-generated/udpa/core/v1/context_params.upb.h +0 -84
  475. data/src/core/ext/upb-generated/udpa/core/v1/resource.upb.h +0 -94
  476. data/src/core/ext/upb-generated/udpa/core/v1/resource_locator.upb.c +0 -54
  477. data/src/core/ext/upb-generated/udpa/core/v1/resource_locator.upb.h +0 -173
  478. data/src/core/ext/upb-generated/udpa/core/v1/resource_name.upb.c +0 -36
  479. data/src/core/ext/upb-generated/udpa/core/v1/resource_name.upb.h +0 -92
  480. data/src/core/ext/upbdefs-generated/udpa/core/v1/authority.upbdefs.c +0 -42
  481. data/src/core/ext/upbdefs-generated/udpa/core/v1/authority.upbdefs.h +0 -35
  482. data/src/core/ext/upbdefs-generated/udpa/core/v1/collection_entry.upbdefs.c +0 -62
  483. data/src/core/ext/upbdefs-generated/udpa/core/v1/collection_entry.upbdefs.h +0 -40
  484. data/src/core/ext/upbdefs-generated/udpa/core/v1/context_params.upbdefs.c +0 -45
  485. data/src/core/ext/upbdefs-generated/udpa/core/v1/context_params.upbdefs.h +0 -40
  486. data/src/core/ext/upbdefs-generated/udpa/core/v1/resource.upbdefs.c +0 -49
  487. data/src/core/ext/upbdefs-generated/udpa/core/v1/resource.upbdefs.h +0 -35
  488. data/src/core/ext/upbdefs-generated/udpa/core/v1/resource_locator.upbdefs.c +0 -68
  489. data/src/core/ext/upbdefs-generated/udpa/core/v1/resource_locator.upbdefs.h +0 -40
  490. data/src/core/ext/upbdefs-generated/udpa/core/v1/resource_name.upbdefs.c +0 -51
  491. data/src/core/ext/upbdefs-generated/udpa/core/v1/resource_name.upbdefs.h +0 -35
  492. data/src/core/lib/iomgr/iomgr_posix.h +0 -26
  493. data/src/core/lib/security/authorization/authorization_engine.cc +0 -177
  494. data/src/core/lib/security/authorization/authorization_engine.h +0 -84
  495. data/src/core/lib/security/authorization/evaluate_args.cc +0 -148
  496. data/src/core/lib/security/authorization/evaluate_args.h +0 -59
  497. data/src/core/lib/security/authorization/mock_cel/activation.h +0 -57
  498. data/src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h +0 -44
  499. data/src/core/lib/security/authorization/mock_cel/cel_expression.h +0 -69
  500. data/src/core/lib/security/authorization/mock_cel/cel_value.h +0 -97
  501. data/src/core/lib/security/authorization/mock_cel/evaluator_core.h +0 -67
  502. data/src/core/lib/security/authorization/mock_cel/flat_expr_builder.h +0 -57
  503. data/third_party/abseil-cpp/absl/container/flat_hash_set.h +0 -504
  504. data/third_party/upb/upb/json_decode.c +0 -1443
  505. data/third_party/upb/upb/json_decode.h +0 -23
  506. data/third_party/upb/upb/json_encode.c +0 -713
  507. data/third_party/upb/upb/json_encode.h +0 -36
@@ -0,0 +1,50 @@
1
+ /* This file was generated by upbc (the upb compiler) from the input
2
+ * file:
3
+ *
4
+ * xds/core/v3/resource_name.proto
5
+ *
6
+ * Do not edit -- your changes will be discarded when the file is
7
+ * regenerated. */
8
+
9
+ #include "upb/def.h"
10
+ #include "xds/core/v3/resource_name.upbdefs.h"
11
+
12
+ extern upb_def_init udpa_annotations_status_proto_upbdefinit;
13
+ extern upb_def_init xds_core_v3_context_params_proto_upbdefinit;
14
+ extern upb_def_init validate_validate_proto_upbdefinit;
15
+ extern const upb_msglayout xds_core_v3_ResourceName_msginit;
16
+
17
+ static const upb_msglayout *layouts[1] = {
18
+ &xds_core_v3_ResourceName_msginit,
19
+ };
20
+
21
+ static const char descriptor[367] = {'\n', '\037', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'n', 'a',
22
+ 'm', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\013', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\035', 'u', 'd',
23
+ 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o',
24
+ 't', 'o', '\032', ' ', 'x', 'd', 's', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'p',
25
+ 'a', 'r', 'a', 'm', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l',
26
+ 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\240', '\001', '\n', '\014', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'N',
27
+ 'a', 'm', 'e', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\002', 'i', 'd', '\022', '\034', '\n', '\t', 'a', 'u',
28
+ 't', 'h', 'o', 'r', 'i', 't', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', '\022',
29
+ ',', '\n', '\r', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'B', '\007', '\372',
30
+ 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\014', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'T', 'y', 'p', 'e', '\022', '4', '\n', '\007', 'c',
31
+ 'o', 'n', 't', 'e', 'x', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\032', '.', 'x', 'd', 's', '.', 'c', 'o', 'r', 'e', '.', 'v',
32
+ '3', '.', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', 'r', 'a', 'm', 's', 'R', '\007', 'c', 'o', 'n', 't', 'e', 'x', 't', 'B',
33
+ ':', '\n', '\033', 'c', 'o', 'm', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'x', 'd', 's', '.', 'c', 'o',
34
+ 'r', 'e', '.', 'v', '3', 'B', '\021', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'N', 'a', 'm', 'e', 'P', 'r', 'o', 't', 'o', 'P',
35
+ '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\010', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
36
+ };
37
+
38
+ static upb_def_init *deps[4] = {
39
+ &udpa_annotations_status_proto_upbdefinit,
40
+ &xds_core_v3_context_params_proto_upbdefinit,
41
+ &validate_validate_proto_upbdefinit,
42
+ NULL
43
+ };
44
+
45
+ upb_def_init xds_core_v3_resource_name_proto_upbdefinit = {
46
+ deps,
47
+ layouts,
48
+ "xds/core/v3/resource_name.proto",
49
+ UPB_STRVIEW_INIT(descriptor, 367)
50
+ };
@@ -0,0 +1,35 @@
1
+ /* This file was generated by upbc (the upb compiler) from the input
2
+ * file:
3
+ *
4
+ * xds/core/v3/resource_name.proto
5
+ *
6
+ * Do not edit -- your changes will be discarded when the file is
7
+ * regenerated. */
8
+
9
+ #ifndef XDS_CORE_V3_RESOURCE_NAME_PROTO_UPBDEFS_H_
10
+ #define XDS_CORE_V3_RESOURCE_NAME_PROTO_UPBDEFS_H_
11
+
12
+ #include "upb/def.h"
13
+ #include "upb/port_def.inc"
14
+ #ifdef __cplusplus
15
+ extern "C" {
16
+ #endif
17
+
18
+ #include "upb/def.h"
19
+
20
+ #include "upb/port_def.inc"
21
+
22
+ extern upb_def_init xds_core_v3_resource_name_proto_upbdefinit;
23
+
24
+ UPB_INLINE const upb_msgdef *xds_core_v3_ResourceName_getmsgdef(upb_symtab *s) {
25
+ _upb_symtab_loaddefinit(s, &xds_core_v3_resource_name_proto_upbdefinit);
26
+ return upb_symtab_lookupmsg(s, "xds.core.v3.ResourceName");
27
+ }
28
+
29
+ #ifdef __cplusplus
30
+ } /* extern "C" */
31
+ #endif
32
+
33
+ #include "upb/port_undef.inc"
34
+
35
+ #endif /* XDS_CORE_V3_RESOURCE_NAME_PROTO_UPBDEFS_H_ */
@@ -28,26 +28,13 @@
28
28
  #include "absl/strings/str_format.h"
29
29
  #include "absl/strings/str_join.h"
30
30
  #include "absl/strings/str_split.h"
31
-
32
- #include "upb/upb.hpp"
33
-
34
- #include <grpc/impl/codegen/log.h>
35
- #include <grpc/support/alloc.h>
36
- #include <grpc/support/string_util.h>
37
-
38
- #include "src/core/ext/xds/xds_api.h"
39
- #include "src/core/lib/gpr/env.h"
40
- #include "src/core/lib/gpr/string.h"
41
- #include "src/core/lib/gpr/useful.h"
42
- #include "src/core/lib/iomgr/error.h"
43
- #include "src/core/lib/iomgr/sockaddr_utils.h"
44
- #include "src/core/lib/slice/slice_utils.h"
45
-
31
+ #include "envoy/admin/v3/config_dump.upb.h"
46
32
  #include "envoy/config/cluster/v3/circuit_breaker.upb.h"
47
33
  #include "envoy/config/cluster/v3/cluster.upb.h"
48
34
  #include "envoy/config/cluster/v3/cluster.upbdefs.h"
49
35
  #include "envoy/config/core/v3/address.upb.h"
50
36
  #include "envoy/config/core/v3/base.upb.h"
37
+ #include "envoy/config/core/v3/base.upbdefs.h"
51
38
  #include "envoy/config/core/v3/config_source.upb.h"
52
39
  #include "envoy/config/core/v3/health_check.upb.h"
53
40
  #include "envoy/config/core/v3/protocol.upb.h"
@@ -57,12 +44,19 @@
57
44
  #include "envoy/config/endpoint/v3/load_report.upb.h"
58
45
  #include "envoy/config/listener/v3/api_listener.upb.h"
59
46
  #include "envoy/config/listener/v3/listener.upb.h"
47
+ #include "envoy/config/listener/v3/listener.upbdefs.h"
48
+ #include "envoy/config/listener/v3/listener_components.upb.h"
60
49
  #include "envoy/config/route/v3/route.upb.h"
61
50
  #include "envoy/config/route/v3/route.upbdefs.h"
62
51
  #include "envoy/config/route/v3/route_components.upb.h"
52
+ #include "envoy/config/route/v3/route_components.upbdefs.h"
53
+ #include "envoy/extensions/clusters/aggregate/v3/cluster.upb.h"
54
+ #include "envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h"
63
55
  #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h"
56
+ #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h"
64
57
  #include "envoy/extensions/transport_sockets/tls/v3/common.upb.h"
65
58
  #include "envoy/extensions/transport_sockets/tls/v3/tls.upb.h"
59
+ #include "envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.h"
66
60
  #include "envoy/service/cluster/v3/cds.upb.h"
67
61
  #include "envoy/service/cluster/v3/cds.upbdefs.h"
68
62
  #include "envoy/service/discovery/v3/discovery.upb.h"
@@ -74,6 +68,8 @@
74
68
  #include "envoy/service/load_stats/v3/lrs.upbdefs.h"
75
69
  #include "envoy/service/route/v3/rds.upb.h"
76
70
  #include "envoy/service/route/v3/rds.upbdefs.h"
71
+ #include "envoy/service/status/v3/csds.upb.h"
72
+ #include "envoy/service/status/v3/csds.upbdefs.h"
77
73
  #include "envoy/type/matcher/v3/regex.upb.h"
78
74
  #include "envoy/type/matcher/v3/string.upb.h"
79
75
  #include "envoy/type/v3/percent.upb.h"
@@ -81,18 +77,49 @@
81
77
  #include "google/protobuf/any.upb.h"
82
78
  #include "google/protobuf/duration.upb.h"
83
79
  #include "google/protobuf/struct.upb.h"
80
+ #include "google/protobuf/timestamp.upb.h"
84
81
  #include "google/protobuf/wrappers.upb.h"
85
82
  #include "google/rpc/status.upb.h"
83
+ #include "udpa/type/v1/typed_struct.upb.h"
86
84
  #include "upb/text_encode.h"
87
85
  #include "upb/upb.h"
86
+ #include "upb/upb.hpp"
87
+
88
+ #include <grpc/impl/codegen/log.h>
89
+ #include <grpc/support/alloc.h>
90
+ #include <grpc/support/string_util.h>
91
+
92
+ #include "src/core/ext/xds/xds_api.h"
93
+ #include "src/core/lib/gpr/env.h"
94
+ #include "src/core/lib/gpr/string.h"
95
+ #include "src/core/lib/gpr/useful.h"
96
+ #include "src/core/lib/gprpp/host_port.h"
97
+ #include "src/core/lib/iomgr/error.h"
98
+ #include "src/core/lib/iomgr/sockaddr.h"
99
+ #include "src/core/lib/iomgr/sockaddr_utils.h"
100
+ #include "src/core/lib/iomgr/socket_utils.h"
101
+ #include "src/core/lib/slice/slice_utils.h"
88
102
 
89
103
  namespace grpc_core {
90
104
 
91
- // TODO (donnadionne): Check to see if timeout is enabled, this will be
92
- // removed once timeout feature is fully integration-tested and enabled by
105
+ // TODO(donnadionne): Check to see if cluster types aggregate_cluster and
106
+ // logical_dns are enabled, this will be
107
+ // removed once the cluster types are fully integration-tested and enabled by
108
+ // default.
109
+ bool XdsAggregateAndLogicalDnsClusterEnabled() {
110
+ char* value = gpr_getenv(
111
+ "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER");
112
+ bool parsed_value;
113
+ bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value);
114
+ gpr_free(value);
115
+ return parse_succeeded && parsed_value;
116
+ }
117
+
118
+ // TODO(donnadionne): Check to see if ring hash policy is enabled, this will be
119
+ // removed once ring hash policy is fully integration-tested and enabled by
93
120
  // default.
94
- bool XdsTimeoutEnabled() {
95
- char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT");
121
+ bool XdsRingHashEnabled() {
122
+ char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH");
96
123
  bool parsed_value;
97
124
  bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value);
98
125
  gpr_free(value);
@@ -111,160 +138,80 @@ bool XdsSecurityEnabled() {
111
138
  }
112
139
 
113
140
  //
114
- // XdsApi::Route::Matchers::PathMatcher
141
+ // XdsApi::Route::HashPolicy
115
142
  //
116
143
 
117
- XdsApi::Route::Matchers::PathMatcher::PathMatcher(const PathMatcher& other)
118
- : type(other.type), case_sensitive(other.case_sensitive) {
119
- if (type == PathMatcherType::REGEX) {
120
- RE2::Options options;
121
- options.set_case_sensitive(case_sensitive);
122
- regex_matcher =
123
- absl::make_unique<RE2>(other.regex_matcher->pattern(), options);
124
- } else {
125
- string_matcher = other.string_matcher;
144
+ XdsApi::Route::HashPolicy::HashPolicy(const HashPolicy& other)
145
+ : type(other.type),
146
+ header_name(other.header_name),
147
+ regex_substitution(other.regex_substitution) {
148
+ if (other.regex != nullptr) {
149
+ regex =
150
+ absl::make_unique<RE2>(other.regex->pattern(), other.regex->options());
126
151
  }
127
152
  }
128
153
 
129
- XdsApi::Route::Matchers::PathMatcher& XdsApi::Route::Matchers::PathMatcher::
130
- operator=(const PathMatcher& other) {
154
+ XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=(
155
+ const HashPolicy& other) {
131
156
  type = other.type;
132
- case_sensitive = other.case_sensitive;
133
- if (type == PathMatcherType::REGEX) {
134
- RE2::Options options;
135
- options.set_case_sensitive(case_sensitive);
136
- regex_matcher =
137
- absl::make_unique<RE2>(other.regex_matcher->pattern(), options);
138
- } else {
139
- string_matcher = other.string_matcher;
157
+ header_name = other.header_name;
158
+ if (other.regex != nullptr) {
159
+ regex =
160
+ absl::make_unique<RE2>(other.regex->pattern(), other.regex->options());
140
161
  }
162
+ regex_substitution = other.regex_substitution;
141
163
  return *this;
142
164
  }
143
165
 
144
- bool XdsApi::Route::Matchers::PathMatcher::operator==(
145
- const PathMatcher& other) const {
146
- if (type != other.type) return false;
147
- if (case_sensitive != other.case_sensitive) return false;
148
- if (type == PathMatcherType::REGEX) {
149
- // Should never be null.
150
- if (regex_matcher == nullptr || other.regex_matcher == nullptr) {
151
- return false;
152
- }
153
- return regex_matcher->pattern() == other.regex_matcher->pattern();
154
- }
155
- return string_matcher == other.string_matcher;
156
- }
157
-
158
- std::string XdsApi::Route::Matchers::PathMatcher::ToString() const {
159
- std::string path_type_string;
160
- switch (type) {
161
- case PathMatcherType::PATH:
162
- path_type_string = "path match";
163
- break;
164
- case PathMatcherType::PREFIX:
165
- path_type_string = "prefix match";
166
- break;
167
- case PathMatcherType::REGEX:
168
- path_type_string = "regex match";
169
- break;
170
- default:
171
- break;
172
- }
173
- return absl::StrFormat("Path %s:%s%s", path_type_string,
174
- type == PathMatcherType::REGEX
175
- ? regex_matcher->pattern()
176
- : string_matcher,
177
- case_sensitive ? "" : "[case_sensitive=false]");
178
- }
179
-
180
- //
181
- // XdsApi::Route::Matchers::HeaderMatcher
182
- //
183
-
184
- XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcher(
185
- const HeaderMatcher& other)
186
- : name(other.name), type(other.type), invert_match(other.invert_match) {
187
- switch (type) {
188
- case HeaderMatcherType::REGEX:
189
- regex_match = absl::make_unique<RE2>(other.regex_match->pattern());
190
- break;
191
- case HeaderMatcherType::RANGE:
192
- range_start = other.range_start;
193
- range_end = other.range_end;
194
- break;
195
- case HeaderMatcherType::PRESENT:
196
- present_match = other.present_match;
197
- break;
198
- default:
199
- string_matcher = other.string_matcher;
200
- }
201
- }
166
+ XdsApi::Route::HashPolicy::HashPolicy(HashPolicy&& other) noexcept
167
+ : type(other.type),
168
+ header_name(std::move(other.header_name)),
169
+ regex(std::move(other.regex)),
170
+ regex_substitution(std::move(other.regex_substitution)) {}
202
171
 
203
- XdsApi::Route::Matchers::HeaderMatcher& XdsApi::Route::Matchers::HeaderMatcher::
204
- operator=(const HeaderMatcher& other) {
205
- name = other.name;
172
+ XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=(
173
+ HashPolicy&& other) noexcept {
206
174
  type = other.type;
207
- invert_match = other.invert_match;
208
- switch (type) {
209
- case HeaderMatcherType::REGEX:
210
- regex_match = absl::make_unique<RE2>(other.regex_match->pattern());
211
- break;
212
- case HeaderMatcherType::RANGE:
213
- range_start = other.range_start;
214
- range_end = other.range_end;
215
- break;
216
- case HeaderMatcherType::PRESENT:
217
- present_match = other.present_match;
218
- break;
219
- default:
220
- string_matcher = other.string_matcher;
221
- }
175
+ header_name = std::move(other.header_name);
176
+ regex = std::move(other.regex);
177
+ regex_substitution = std::move(other.regex_substitution);
222
178
  return *this;
223
179
  }
224
180
 
225
- bool XdsApi::Route::Matchers::HeaderMatcher::operator==(
226
- const HeaderMatcher& other) const {
227
- if (name != other.name) return false;
181
+ bool XdsApi::Route::HashPolicy::HashPolicy::operator==(
182
+ const HashPolicy& other) const {
228
183
  if (type != other.type) return false;
229
- if (invert_match != other.invert_match) return false;
230
- switch (type) {
231
- case HeaderMatcherType::REGEX:
232
- return regex_match->pattern() != other.regex_match->pattern();
233
- case HeaderMatcherType::RANGE:
234
- return range_start != other.range_start && range_end != other.range_end;
235
- case HeaderMatcherType::PRESENT:
236
- return present_match != other.present_match;
237
- default:
238
- return string_matcher != other.string_matcher;
184
+ if (type == Type::HEADER) {
185
+ if (regex == nullptr) {
186
+ if (other.regex != nullptr) return false;
187
+ } else {
188
+ if (other.regex == nullptr) return false;
189
+ return header_name == other.header_name &&
190
+ regex->pattern() == other.regex->pattern() &&
191
+ regex_substitution == other.regex_substitution;
192
+ }
239
193
  }
194
+ return true;
240
195
  }
241
196
 
242
- std::string XdsApi::Route::Matchers::HeaderMatcher::ToString() const {
197
+ std::string XdsApi::Route::HashPolicy::ToString() const {
198
+ std::vector<std::string> contents;
243
199
  switch (type) {
244
- case HeaderMatcherType::EXACT:
245
- return absl::StrFormat("Header exact match:%s %s:%s",
246
- invert_match ? " not" : "", name, string_matcher);
247
- case HeaderMatcherType::REGEX:
248
- return absl::StrFormat("Header regex match:%s %s:%s",
249
- invert_match ? " not" : "", name,
250
- regex_match->pattern());
251
- case HeaderMatcherType::RANGE:
252
- return absl::StrFormat("Header range match:%s %s:[%d, %d)",
253
- invert_match ? " not" : "", name, range_start,
254
- range_end);
255
- case HeaderMatcherType::PRESENT:
256
- return absl::StrFormat("Header present match:%s %s:%s",
257
- invert_match ? " not" : "", name,
258
- present_match ? "true" : "false");
259
- case HeaderMatcherType::PREFIX:
260
- return absl::StrFormat("Header prefix match:%s %s:%s",
261
- invert_match ? " not" : "", name, string_matcher);
262
- case HeaderMatcherType::SUFFIX:
263
- return absl::StrFormat("Header suffix match:%s %s:%s",
264
- invert_match ? " not" : "", name, string_matcher);
265
- default:
266
- return "";
200
+ case Type::HEADER:
201
+ contents.push_back("type=HEADER");
202
+ break;
203
+ case Type::CHANNEL_ID:
204
+ contents.push_back("type=CHANNEL_ID");
205
+ break;
206
+ }
207
+ contents.push_back(
208
+ absl::StrFormat("terminal=%s", terminal ? "true" : "false"));
209
+ if (type == Type::HEADER) {
210
+ contents.push_back(absl::StrFormat(
211
+ "Header %s:/%s/%s", header_name,
212
+ (regex == nullptr) ? "" : regex->pattern(), regex_substitution));
267
213
  }
214
+ return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
268
215
  }
269
216
 
270
217
  //
@@ -273,7 +220,8 @@ std::string XdsApi::Route::Matchers::HeaderMatcher::ToString() const {
273
220
 
274
221
  std::string XdsApi::Route::Matchers::ToString() const {
275
222
  std::vector<std::string> contents;
276
- contents.push_back(path_matcher.ToString());
223
+ contents.push_back(
224
+ absl::StrFormat("PathMatcher{%s}", path_matcher.ToString()));
277
225
  for (const HeaderMatcher& header_matcher : header_matchers) {
278
226
  contents.push_back(header_matcher.ToString());
279
227
  }
@@ -285,12 +233,28 @@ std::string XdsApi::Route::Matchers::ToString() const {
285
233
  }
286
234
 
287
235
  std::string XdsApi::Route::ClusterWeight::ToString() const {
288
- return absl::StrFormat("{cluster=%s, weight=%d}", name, weight);
236
+ std::vector<std::string> contents;
237
+ contents.push_back(absl::StrCat("cluster=", name));
238
+ contents.push_back(absl::StrCat("weight=", weight));
239
+ if (!typed_per_filter_config.empty()) {
240
+ std::vector<std::string> parts;
241
+ for (const auto& p : typed_per_filter_config) {
242
+ const std::string& key = p.first;
243
+ const auto& config = p.second;
244
+ parts.push_back(absl::StrCat(key, "=", config.ToString()));
245
+ }
246
+ contents.push_back(absl::StrCat("typed_per_filter_config={",
247
+ absl::StrJoin(parts, ", "), "}"));
248
+ }
249
+ return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
289
250
  }
290
251
 
291
252
  std::string XdsApi::Route::ToString() const {
292
253
  std::vector<std::string> contents;
293
254
  contents.push_back(matchers.ToString());
255
+ for (const HashPolicy& hash_policy : hash_policies) {
256
+ contents.push_back(absl::StrCat("hash_policy=", hash_policy.ToString()));
257
+ }
294
258
  if (!cluster_name.empty()) {
295
259
  contents.push_back(absl::StrFormat("Cluster name: %s", cluster_name));
296
260
  }
@@ -300,6 +264,15 @@ std::string XdsApi::Route::ToString() const {
300
264
  if (max_stream_duration.has_value()) {
301
265
  contents.push_back(max_stream_duration->ToString());
302
266
  }
267
+ if (!typed_per_filter_config.empty()) {
268
+ contents.push_back("typed_per_filter_config={");
269
+ for (const auto& p : typed_per_filter_config) {
270
+ const std::string& name = p.first;
271
+ const auto& config = p.second;
272
+ contents.push_back(absl::StrCat(" ", name, "=", config.ToString()));
273
+ }
274
+ contents.push_back("}");
275
+ }
303
276
  return absl::StrJoin(contents, "\n");
304
277
  }
305
278
 
@@ -322,6 +295,14 @@ std::string XdsApi::RdsUpdate::ToString() const {
322
295
  vhosts.push_back("\n }\n");
323
296
  }
324
297
  vhosts.push_back(" ]\n");
298
+ vhosts.push_back(" typed_per_filter_config={\n");
299
+ for (const auto& p : vhost.typed_per_filter_config) {
300
+ const std::string& name = p.first;
301
+ const auto& config = p.second;
302
+ vhosts.push_back(
303
+ absl::StrCat(" ", name, "=", config.ToString(), "\n"));
304
+ }
305
+ vhosts.push_back(" }\n");
325
306
  vhosts.push_back("]\n");
326
307
  }
327
308
  return absl::StrJoin(vhosts, "");
@@ -425,102 +406,6 @@ XdsApi::RdsUpdate::VirtualHost* XdsApi::RdsUpdate::FindVirtualHostForDomain(
425
406
  return target_vhost;
426
407
  }
427
408
 
428
- //
429
- // XdsApi::StringMatcher
430
- //
431
-
432
- XdsApi::StringMatcher::StringMatcher(StringMatcherType type,
433
- const std::string& matcher,
434
- bool ignore_case)
435
- : type_(type), ignore_case_(ignore_case) {
436
- if (type_ == StringMatcherType::SAFE_REGEX) {
437
- regex_matcher_ = absl::make_unique<RE2>(matcher);
438
- } else {
439
- string_matcher_ = matcher;
440
- }
441
- }
442
-
443
- XdsApi::StringMatcher::StringMatcher(const StringMatcher& other)
444
- : type_(other.type_), ignore_case_(other.ignore_case_) {
445
- switch (type_) {
446
- case StringMatcherType::SAFE_REGEX:
447
- regex_matcher_ = absl::make_unique<RE2>(other.regex_matcher_->pattern());
448
- break;
449
- default:
450
- string_matcher_ = other.string_matcher_;
451
- }
452
- }
453
-
454
- XdsApi::StringMatcher& XdsApi::StringMatcher::operator=(
455
- const StringMatcher& other) {
456
- type_ = other.type_;
457
- switch (type_) {
458
- case StringMatcherType::SAFE_REGEX:
459
- regex_matcher_ = absl::make_unique<RE2>(other.regex_matcher_->pattern());
460
- break;
461
- default:
462
- string_matcher_ = other.string_matcher_;
463
- }
464
- ignore_case_ = other.ignore_case_;
465
- return *this;
466
- }
467
-
468
- bool XdsApi::StringMatcher::operator==(const StringMatcher& other) const {
469
- if (type_ != other.type_ || ignore_case_ != other.ignore_case_) return false;
470
- switch (type_) {
471
- case StringMatcherType::SAFE_REGEX:
472
- return regex_matcher_->pattern() == other.regex_matcher_->pattern();
473
- default:
474
- return string_matcher_ == other.string_matcher_;
475
- }
476
- }
477
-
478
- bool XdsApi::StringMatcher::Match(absl::string_view value) const {
479
- switch (type_) {
480
- case XdsApi::StringMatcher::StringMatcherType::EXACT:
481
- return ignore_case_ ? absl::EqualsIgnoreCase(value, string_matcher_)
482
- : value == string_matcher_;
483
- case XdsApi::StringMatcher::StringMatcherType::PREFIX:
484
- return ignore_case_ ? absl::StartsWithIgnoreCase(value, string_matcher_)
485
- : absl::StartsWith(value, string_matcher_);
486
- case XdsApi::StringMatcher::StringMatcherType::SUFFIX:
487
- return ignore_case_ ? absl::EndsWithIgnoreCase(value, string_matcher_)
488
- : absl::EndsWith(value, string_matcher_);
489
- case XdsApi::StringMatcher::StringMatcherType::CONTAINS:
490
- return ignore_case_
491
- ? absl::StrContains(absl::AsciiStrToLower(value),
492
- absl::AsciiStrToLower(string_matcher_))
493
- : absl::StrContains(value, string_matcher_);
494
- case XdsApi::StringMatcher::StringMatcherType::SAFE_REGEX:
495
- // ignore_case_ is ignored for SAFE_REGEX
496
- return RE2::FullMatch(std::string(value), *regex_matcher_);
497
- default:
498
- return false;
499
- }
500
- }
501
-
502
- std::string XdsApi::StringMatcher::ToString() const {
503
- switch (type_) {
504
- case StringMatcherType::EXACT:
505
- return absl::StrFormat("StringMatcher{exact=%s%s}", string_matcher_,
506
- ignore_case_ ? ", ignore_case" : "");
507
- case StringMatcherType::PREFIX:
508
- return absl::StrFormat("StringMatcher{prefix=%s%s}", string_matcher_,
509
- ignore_case_ ? ", ignore_case" : "");
510
- case StringMatcherType::SUFFIX:
511
- return absl::StrFormat("StringMatcher{suffix=%s%s}", string_matcher_,
512
- ignore_case_ ? ", ignore_case" : "");
513
- case StringMatcherType::CONTAINS:
514
- return absl::StrFormat("StringMatcher{contains=%s%s}", string_matcher_,
515
- ignore_case_ ? ", ignore_case" : "");
516
- case StringMatcherType::SAFE_REGEX:
517
- return absl::StrFormat("StringMatcher{safe_regex=%s}",
518
- regex_matcher_->pattern());
519
- default:
520
- return "";
521
- }
522
- }
523
-
524
409
  //
525
410
  // XdsApi::CommonTlsContext::CertificateValidationContext
526
411
  //
@@ -609,6 +494,204 @@ bool XdsApi::CommonTlsContext::Empty() const {
609
494
  combined_validation_context.Empty();
610
495
  }
611
496
 
497
+ //
498
+ // XdsApi::DownstreamTlsContext
499
+ //
500
+
501
+ std::string XdsApi::DownstreamTlsContext::ToString() const {
502
+ return absl::StrFormat("common_tls_context=%s, require_client_certificate=%s",
503
+ common_tls_context.ToString(),
504
+ require_client_certificate ? "true" : "false");
505
+ }
506
+
507
+ bool XdsApi::DownstreamTlsContext::Empty() const {
508
+ return common_tls_context.Empty();
509
+ }
510
+
511
+ //
512
+ // XdsApi::LdsUpdate::HttpConnectionManager
513
+ //
514
+
515
+ std::string XdsApi::LdsUpdate::HttpConnectionManager::ToString() const {
516
+ absl::InlinedVector<std::string, 4> contents;
517
+ contents.push_back(absl::StrFormat(
518
+ "route_config_name=%s",
519
+ !route_config_name.empty() ? route_config_name.c_str() : "<inlined>"));
520
+ contents.push_back(absl::StrFormat("http_max_stream_duration=%s",
521
+ http_max_stream_duration.ToString()));
522
+ if (rds_update.has_value()) {
523
+ contents.push_back(
524
+ absl::StrFormat("rds_update=%s", rds_update->ToString()));
525
+ }
526
+ if (!http_filters.empty()) {
527
+ std::vector<std::string> filter_strings;
528
+ for (const auto& http_filter : http_filters) {
529
+ filter_strings.push_back(http_filter.ToString());
530
+ }
531
+ contents.push_back(absl::StrCat("http_filters=[",
532
+ absl::StrJoin(filter_strings, ", "), "]"));
533
+ }
534
+ return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
535
+ }
536
+
537
+ //
538
+ // XdsApi::LdsUpdate::HttpFilter
539
+ //
540
+
541
+ std::string XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter::ToString()
542
+ const {
543
+ return absl::StrCat("{name=", name, ", config=", config.ToString(), "}");
544
+ }
545
+
546
+ //
547
+ // XdsApi::LdsUpdate::FilterChainData
548
+ //
549
+
550
+ std::string XdsApi::LdsUpdate::FilterChainData::ToString() const {
551
+ return absl::StrCat(
552
+ "{downstream_tls_context=", downstream_tls_context.ToString(),
553
+ " http_connection_manager=", http_connection_manager.ToString(), "}");
554
+ }
555
+
556
+ //
557
+ // XdsApi::LdsUpdate::FilterChainMap::CidrRange
558
+ //
559
+
560
+ std::string XdsApi::LdsUpdate::FilterChainMap::CidrRange::ToString() const {
561
+ return absl::StrCat(
562
+ "{address_prefix=", grpc_sockaddr_to_string(&address, false),
563
+ ", prefix_len=", prefix_len, "}");
564
+ }
565
+
566
+ //
567
+ // FilterChain
568
+ //
569
+
570
+ struct FilterChain {
571
+ struct FilterChainMatch {
572
+ uint32_t destination_port = 0;
573
+ std::vector<XdsApi::LdsUpdate::FilterChainMap::CidrRange> prefix_ranges;
574
+ XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType source_type =
575
+ XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::kAny;
576
+ std::vector<XdsApi::LdsUpdate::FilterChainMap::CidrRange>
577
+ source_prefix_ranges;
578
+ std::vector<uint32_t> source_ports;
579
+ std::vector<std::string> server_names;
580
+ std::string transport_protocol;
581
+ std::vector<std::string> application_protocols;
582
+
583
+ std::string ToString() const;
584
+ } filter_chain_match;
585
+
586
+ std::shared_ptr<XdsApi::LdsUpdate::FilterChainData> filter_chain_data;
587
+ };
588
+
589
+ std::string FilterChain::FilterChainMatch::ToString() const {
590
+ absl::InlinedVector<std::string, 8> contents;
591
+ if (destination_port != 0) {
592
+ contents.push_back(absl::StrCat("destination_port=", destination_port));
593
+ }
594
+ if (!prefix_ranges.empty()) {
595
+ std::vector<std::string> prefix_ranges_content;
596
+ for (const auto& range : prefix_ranges) {
597
+ prefix_ranges_content.push_back(range.ToString());
598
+ }
599
+ contents.push_back(absl::StrCat(
600
+ "prefix_ranges={", absl::StrJoin(prefix_ranges_content, ", "), "}"));
601
+ }
602
+ if (source_type == XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::
603
+ kSameIpOrLoopback) {
604
+ contents.push_back("source_type=SAME_IP_OR_LOOPBACK");
605
+ } else if (source_type == XdsApi::LdsUpdate::FilterChainMap::
606
+ ConnectionSourceType::kExternal) {
607
+ contents.push_back("source_type=EXTERNAL");
608
+ }
609
+ if (!source_prefix_ranges.empty()) {
610
+ std::vector<std::string> source_prefix_ranges_content;
611
+ for (const auto& range : source_prefix_ranges) {
612
+ source_prefix_ranges_content.push_back(range.ToString());
613
+ }
614
+ contents.push_back(
615
+ absl::StrCat("source_prefix_ranges={",
616
+ absl::StrJoin(source_prefix_ranges_content, ", "), "}"));
617
+ }
618
+ if (!source_ports.empty()) {
619
+ contents.push_back(
620
+ absl::StrCat("source_ports={", absl::StrJoin(source_ports, ", "), "}"));
621
+ }
622
+ if (!server_names.empty()) {
623
+ contents.push_back(
624
+ absl::StrCat("server_names={", absl::StrJoin(server_names, ", "), "}"));
625
+ }
626
+ if (!transport_protocol.empty()) {
627
+ contents.push_back(absl::StrCat("transport_protocol=", transport_protocol));
628
+ }
629
+ if (!application_protocols.empty()) {
630
+ contents.push_back(absl::StrCat("application_protocols={",
631
+ absl::StrJoin(application_protocols, ", "),
632
+ "}"));
633
+ }
634
+ return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
635
+ }
636
+
637
+ //
638
+ // XdsApi::LdsUpdate::FilterChainMap
639
+ //
640
+
641
+ std::string XdsApi::LdsUpdate::FilterChainMap::ToString() const {
642
+ std::vector<std::string> contents;
643
+ for (const auto& destination_ip : destination_ip_vector) {
644
+ for (int source_type = 0; source_type < 3; ++source_type) {
645
+ for (const auto& source_ip :
646
+ destination_ip.source_types_array[source_type]) {
647
+ for (const auto& source_port_pair : source_ip.ports_map) {
648
+ FilterChain::FilterChainMatch filter_chain_match;
649
+ if (destination_ip.prefix_range.has_value()) {
650
+ filter_chain_match.prefix_ranges.push_back(
651
+ *destination_ip.prefix_range);
652
+ }
653
+ filter_chain_match.source_type = static_cast<
654
+ XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType>(
655
+ source_type);
656
+ if (source_ip.prefix_range.has_value()) {
657
+ filter_chain_match.source_prefix_ranges.push_back(
658
+ *source_ip.prefix_range);
659
+ }
660
+ if (source_port_pair.first != 0) {
661
+ filter_chain_match.source_ports.push_back(source_port_pair.first);
662
+ }
663
+ contents.push_back(absl::StrCat(
664
+ "{filter_chain_match=", filter_chain_match.ToString(),
665
+ ", filter_chain=", source_port_pair.second.data->ToString(),
666
+ "}"));
667
+ }
668
+ }
669
+ }
670
+ }
671
+ return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
672
+ }
673
+
674
+ //
675
+ // XdsApi::LdsUpdate
676
+ //
677
+
678
+ std::string XdsApi::LdsUpdate::ToString() const {
679
+ absl::InlinedVector<std::string, 4> contents;
680
+ if (type == ListenerType::kTcpListener) {
681
+ contents.push_back(absl::StrCat("address=", address));
682
+ contents.push_back(
683
+ absl::StrCat("filter_chain_map=", filter_chain_map.ToString()));
684
+ if (default_filter_chain.has_value()) {
685
+ contents.push_back(absl::StrCat("default_filter_chain=",
686
+ default_filter_chain->ToString()));
687
+ }
688
+ } else if (type == ListenerType::kHttpApiListener) {
689
+ contents.push_back(absl::StrFormat("http_connection_manager=%s",
690
+ http_connection_manager.ToString()));
691
+ }
692
+ return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
693
+ }
694
+
612
695
  //
613
696
  // XdsApi::CdsUpdate
614
697
  //
@@ -724,8 +807,13 @@ const char* kCdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.Cluster";
724
807
  const char* kEdsV2TypeUrl =
725
808
  "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
726
809
 
727
- bool IsLds(absl::string_view type_url) {
728
- return type_url == XdsApi::kLdsTypeUrl || type_url == kLdsV2TypeUrl;
810
+ bool IsLds(absl::string_view type_url, bool* is_v2 = nullptr) {
811
+ if (type_url == XdsApi::kLdsTypeUrl) return true;
812
+ if (type_url == kLdsV2TypeUrl) {
813
+ if (is_v2 != nullptr) *is_v2 = true;
814
+ return true;
815
+ }
816
+ return false;
729
817
  }
730
818
 
731
819
  bool IsRds(absl::string_view type_url) {
@@ -749,39 +837,67 @@ XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer,
749
837
  node_(node),
750
838
  build_version_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING, " ",
751
839
  grpc_version_string())),
752
- user_agent_name_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING)) {}
840
+ user_agent_name_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING)) {
841
+ // Populate upb symtab with xDS proto messages that we want to print
842
+ // properly in logs.
843
+ // Note: This won't actually work properly until upb adds support for
844
+ // Any fields in textproto printing (internal b/178821188).
845
+ envoy_config_listener_v3_Listener_getmsgdef(symtab_.ptr());
846
+ envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab_.ptr());
847
+ envoy_config_cluster_v3_Cluster_getmsgdef(symtab_.ptr());
848
+ envoy_extensions_clusters_aggregate_v3_ClusterConfig_getmsgdef(symtab_.ptr());
849
+ envoy_config_cluster_v3_Cluster_getmsgdef(symtab_.ptr());
850
+ envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab_.ptr());
851
+ envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_getmsgdef(
852
+ symtab_.ptr());
853
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef(
854
+ symtab_.ptr());
855
+ // Load HTTP filter proto messages into the upb symtab.
856
+ XdsHttpFilterRegistry::PopulateSymtab(symtab_.ptr());
857
+ }
753
858
 
754
859
  namespace {
755
860
 
861
+ struct EncodingContext {
862
+ XdsClient* client;
863
+ TraceFlag* tracer;
864
+ upb_symtab* symtab;
865
+ upb_arena* arena;
866
+ bool use_v3;
867
+ };
868
+
756
869
  // Works for both std::string and absl::string_view.
757
870
  template <typename T>
758
871
  inline upb_strview StdStringToUpbString(const T& str) {
759
872
  return upb_strview_make(str.data(), str.size());
760
873
  }
761
874
 
762
- void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
763
- const Json& value);
875
+ void PopulateMetadataValue(const EncodingContext& context,
876
+ google_protobuf_Value* value_pb, const Json& value);
764
877
 
765
- void PopulateListValue(upb_arena* arena, google_protobuf_ListValue* list_value,
878
+ void PopulateListValue(const EncodingContext& context,
879
+ google_protobuf_ListValue* list_value,
766
880
  const Json::Array& values) {
767
881
  for (const auto& value : values) {
768
- auto* value_pb = google_protobuf_ListValue_add_values(list_value, arena);
769
- PopulateMetadataValue(arena, value_pb, value);
882
+ auto* value_pb =
883
+ google_protobuf_ListValue_add_values(list_value, context.arena);
884
+ PopulateMetadataValue(context, value_pb, value);
770
885
  }
771
886
  }
772
887
 
773
- void PopulateMetadata(upb_arena* arena, google_protobuf_Struct* metadata_pb,
888
+ void PopulateMetadata(const EncodingContext& context,
889
+ google_protobuf_Struct* metadata_pb,
774
890
  const Json::Object& metadata) {
775
891
  for (const auto& p : metadata) {
776
- google_protobuf_Value* value = google_protobuf_Value_new(arena);
777
- PopulateMetadataValue(arena, value, p.second);
892
+ google_protobuf_Value* value = google_protobuf_Value_new(context.arena);
893
+ PopulateMetadataValue(context, value, p.second);
778
894
  google_protobuf_Struct_fields_set(
779
- metadata_pb, StdStringToUpbString(p.first), value, arena);
895
+ metadata_pb, StdStringToUpbString(p.first), value, context.arena);
780
896
  }
781
897
  }
782
898
 
783
- void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
784
- const Json& value) {
899
+ void PopulateMetadataValue(const EncodingContext& context,
900
+ google_protobuf_Value* value_pb, const Json& value) {
785
901
  switch (value.type()) {
786
902
  case Json::Type::JSON_NULL:
787
903
  google_protobuf_Value_set_null_value(value_pb, 0);
@@ -802,14 +918,14 @@ void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
802
918
  break;
803
919
  case Json::Type::OBJECT: {
804
920
  google_protobuf_Struct* struct_value =
805
- google_protobuf_Value_mutable_struct_value(value_pb, arena);
806
- PopulateMetadata(arena, struct_value, value.object_value());
921
+ google_protobuf_Value_mutable_struct_value(value_pb, context.arena);
922
+ PopulateMetadata(context, struct_value, value.object_value());
807
923
  break;
808
924
  }
809
925
  case Json::Type::ARRAY: {
810
926
  google_protobuf_ListValue* list_value =
811
- google_protobuf_Value_mutable_list_value(value_pb, arena);
812
- PopulateListValue(arena, list_value, value.array_value());
927
+ google_protobuf_Value_mutable_list_value(value_pb, context.arena);
928
+ PopulateListValue(context, list_value, value.array_value());
813
929
  break;
814
930
  }
815
931
  }
@@ -836,7 +952,8 @@ std::string EncodeStringField(uint32_t field_number, const std::string& str) {
836
952
  EncodeVarint(str.size()) + str;
837
953
  }
838
954
 
839
- void PopulateBuildVersion(upb_arena* arena, envoy_config_core_v3_Node* node_msg,
955
+ void PopulateBuildVersion(const EncodingContext& context,
956
+ envoy_config_core_v3_Node* node_msg,
840
957
  const std::string& build_version) {
841
958
  std::string encoded_build_version = EncodeStringField(5, build_version);
842
959
  // TODO(roth): This should use upb_msg_addunknown(), but that API is
@@ -844,10 +961,11 @@ void PopulateBuildVersion(upb_arena* arena, envoy_config_core_v3_Node* node_msg,
844
961
  // API for now. Change this once we upgrade to a version of upb that
845
962
  // fixes this bug.
846
963
  _upb_msg_addunknown(node_msg, encoded_build_version.data(),
847
- encoded_build_version.size(), arena);
964
+ encoded_build_version.size(), context.arena);
848
965
  }
849
966
 
850
- void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
967
+ void PopulateNode(const EncodingContext& context,
968
+ const XdsBootstrap::Node* node,
851
969
  const std::string& build_version,
852
970
  const std::string& user_agent_name,
853
971
  envoy_config_core_v3_Node* node_msg) {
@@ -862,13 +980,13 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
862
980
  }
863
981
  if (!node->metadata.object_value().empty()) {
864
982
  google_protobuf_Struct* metadata =
865
- envoy_config_core_v3_Node_mutable_metadata(node_msg, arena);
866
- PopulateMetadata(arena, metadata, node->metadata.object_value());
983
+ envoy_config_core_v3_Node_mutable_metadata(node_msg, context.arena);
984
+ PopulateMetadata(context, metadata, node->metadata.object_value());
867
985
  }
868
986
  if (!node->locality_region.empty() || !node->locality_zone.empty() ||
869
- !node->locality_subzone.empty()) {
987
+ !node->locality_sub_zone.empty()) {
870
988
  envoy_config_core_v3_Locality* locality =
871
- envoy_config_core_v3_Node_mutable_locality(node_msg, arena);
989
+ envoy_config_core_v3_Node_mutable_locality(node_msg, context.arena);
872
990
  if (!node->locality_region.empty()) {
873
991
  envoy_config_core_v3_Locality_set_region(
874
992
  locality, StdStringToUpbString(node->locality_region));
@@ -877,14 +995,14 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
877
995
  envoy_config_core_v3_Locality_set_zone(
878
996
  locality, StdStringToUpbString(node->locality_zone));
879
997
  }
880
- if (!node->locality_subzone.empty()) {
998
+ if (!node->locality_sub_zone.empty()) {
881
999
  envoy_config_core_v3_Locality_set_sub_zone(
882
- locality, StdStringToUpbString(node->locality_subzone));
1000
+ locality, StdStringToUpbString(node->locality_sub_zone));
883
1001
  }
884
1002
  }
885
1003
  }
886
- if (!use_v3) {
887
- PopulateBuildVersion(arena, node_msg, build_version);
1004
+ if (!context.use_v3) {
1005
+ PopulateBuildVersion(context, node_msg, build_version);
888
1006
  }
889
1007
  envoy_config_core_v3_Node_set_user_agent_name(
890
1008
  node_msg, StdStringToUpbString(user_agent_name));
@@ -892,7 +1010,7 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
892
1010
  node_msg, upb_strview_makez(grpc_version_string()));
893
1011
  envoy_config_core_v3_Node_add_client_features(
894
1012
  node_msg, upb_strview_makez("envoy.lb.does_not_support_overprovisioning"),
895
- arena);
1013
+ context.arena);
896
1014
  }
897
1015
 
898
1016
  inline absl::string_view UpbStringToAbsl(const upb_strview& str) {
@@ -904,24 +1022,25 @@ inline std::string UpbStringToStdString(const upb_strview& str) {
904
1022
  }
905
1023
 
906
1024
  void MaybeLogDiscoveryRequest(
907
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1025
+ const EncodingContext& context,
908
1026
  const envoy_service_discovery_v3_DiscoveryRequest* request) {
909
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
1027
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
910
1028
  gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
911
1029
  const upb_msgdef* msg_type =
912
- envoy_service_discovery_v3_DiscoveryRequest_getmsgdef(symtab);
1030
+ envoy_service_discovery_v3_DiscoveryRequest_getmsgdef(context.symtab);
913
1031
  char buf[10240];
914
1032
  upb_text_encode(request, msg_type, nullptr, 0, buf, sizeof(buf));
915
- gpr_log(GPR_DEBUG, "[xds_client %p] constructed ADS request: %s", client,
916
- buf);
1033
+ gpr_log(GPR_DEBUG, "[xds_client %p] constructed ADS request: %s",
1034
+ context.client, buf);
917
1035
  }
918
1036
  }
919
1037
 
920
1038
  grpc_slice SerializeDiscoveryRequest(
921
- upb_arena* arena, envoy_service_discovery_v3_DiscoveryRequest* request) {
1039
+ const EncodingContext& context,
1040
+ envoy_service_discovery_v3_DiscoveryRequest* request) {
922
1041
  size_t output_length;
923
1042
  char* output = envoy_service_discovery_v3_DiscoveryRequest_serialize(
924
- request, arena, &output_length);
1043
+ request, context.arena, &output_length);
925
1044
  return grpc_slice_from_copied_buffer(output, output_length);
926
1045
  }
927
1046
 
@@ -952,6 +1071,8 @@ grpc_slice XdsApi::CreateAdsRequest(
952
1071
  const std::string& version, const std::string& nonce, grpc_error* error,
953
1072
  bool populate_node) {
954
1073
  upb::Arena arena;
1074
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
1075
+ server.ShouldUseV3()};
955
1076
  // Create a request.
956
1077
  envoy_service_discovery_v3_DiscoveryRequest* request =
957
1078
  envoy_service_discovery_v3_DiscoveryRequest_new(arena.ptr());
@@ -981,12 +1102,9 @@ grpc_slice XdsApi::CreateAdsRequest(
981
1102
  // generate them in the parsing code, and then use that here.
982
1103
  google_rpc_Status_set_code(error_detail, GRPC_STATUS_INVALID_ARGUMENT);
983
1104
  // Error description comes from the error that was passed in.
984
- grpc_slice error_description_slice;
985
- GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
986
- &error_description_slice));
987
- upb_strview error_description_strview =
988
- StdStringToUpbString(StringViewFromSlice(error_description_slice));
989
- google_rpc_Status_set_message(error_detail, error_description_strview);
1105
+ upb_strview error_description =
1106
+ StdStringToUpbString(absl::string_view(grpc_error_string(error)));
1107
+ google_rpc_Status_set_message(error_detail, error_description);
990
1108
  GRPC_ERROR_UNREF(error);
991
1109
  }
992
1110
  // Populate node.
@@ -994,79 +1112,101 @@ grpc_slice XdsApi::CreateAdsRequest(
994
1112
  envoy_config_core_v3_Node* node_msg =
995
1113
  envoy_service_discovery_v3_DiscoveryRequest_mutable_node(request,
996
1114
  arena.ptr());
997
- PopulateNode(arena.ptr(), node_, server.ShouldUseV3(), build_version_,
998
- user_agent_name_, node_msg);
1115
+ PopulateNode(context, node_, build_version_, user_agent_name_, node_msg);
999
1116
  }
1000
1117
  // Add resource_names.
1001
1118
  for (const auto& resource_name : resource_names) {
1002
1119
  envoy_service_discovery_v3_DiscoveryRequest_add_resource_names(
1003
1120
  request, StdStringToUpbString(resource_name), arena.ptr());
1004
1121
  }
1005
- MaybeLogDiscoveryRequest(client_, tracer_, symtab_.ptr(), request);
1006
- return SerializeDiscoveryRequest(arena.ptr(), request);
1122
+ MaybeLogDiscoveryRequest(context, request);
1123
+ return SerializeDiscoveryRequest(context, request);
1007
1124
  }
1008
1125
 
1009
1126
  namespace {
1010
1127
 
1011
1128
  void MaybeLogDiscoveryResponse(
1012
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1129
+ const EncodingContext& context,
1013
1130
  const envoy_service_discovery_v3_DiscoveryResponse* response) {
1014
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
1131
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
1015
1132
  gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
1016
1133
  const upb_msgdef* msg_type =
1017
- envoy_service_discovery_v3_DiscoveryResponse_getmsgdef(symtab);
1134
+ envoy_service_discovery_v3_DiscoveryResponse_getmsgdef(context.symtab);
1018
1135
  char buf[10240];
1019
1136
  upb_text_encode(response, msg_type, nullptr, 0, buf, sizeof(buf));
1020
- gpr_log(GPR_DEBUG, "[xds_client %p] received response: %s", client, buf);
1137
+ gpr_log(GPR_DEBUG, "[xds_client %p] received response: %s", context.client,
1138
+ buf);
1139
+ }
1140
+ }
1141
+
1142
+ void MaybeLogHttpConnectionManager(
1143
+ const EncodingContext& context,
1144
+ const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager*
1145
+ http_connection_manager_config) {
1146
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
1147
+ gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
1148
+ const upb_msgdef* msg_type =
1149
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef(
1150
+ context.symtab);
1151
+ char buf[10240];
1152
+ upb_text_encode(http_connection_manager_config, msg_type, nullptr, 0, buf,
1153
+ sizeof(buf));
1154
+ gpr_log(GPR_DEBUG, "[xds_client %p] HttpConnectionManager: %s",
1155
+ context.client, buf);
1021
1156
  }
1022
1157
  }
1023
1158
 
1024
1159
  void MaybeLogRouteConfiguration(
1025
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1160
+ const EncodingContext& context,
1026
1161
  const envoy_config_route_v3_RouteConfiguration* route_config) {
1027
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
1162
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
1028
1163
  gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
1029
1164
  const upb_msgdef* msg_type =
1030
- envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab);
1165
+ envoy_config_route_v3_RouteConfiguration_getmsgdef(context.symtab);
1031
1166
  char buf[10240];
1032
1167
  upb_text_encode(route_config, msg_type, nullptr, 0, buf, sizeof(buf));
1033
- gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", client, buf);
1168
+ gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", context.client,
1169
+ buf);
1034
1170
  }
1035
1171
  }
1036
1172
 
1037
- void MaybeLogCluster(XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1173
+ void MaybeLogCluster(const EncodingContext& context,
1038
1174
  const envoy_config_cluster_v3_Cluster* cluster) {
1039
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
1175
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
1040
1176
  gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
1041
1177
  const upb_msgdef* msg_type =
1042
- envoy_config_cluster_v3_Cluster_getmsgdef(symtab);
1178
+ envoy_config_cluster_v3_Cluster_getmsgdef(context.symtab);
1043
1179
  char buf[10240];
1044
1180
  upb_text_encode(cluster, msg_type, nullptr, 0, buf, sizeof(buf));
1045
- gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", client, buf);
1181
+ gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", context.client, buf);
1046
1182
  }
1047
1183
  }
1048
1184
 
1049
1185
  void MaybeLogClusterLoadAssignment(
1050
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1186
+ const EncodingContext& context,
1051
1187
  const envoy_config_endpoint_v3_ClusterLoadAssignment* cla) {
1052
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
1188
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
1053
1189
  gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
1054
1190
  const upb_msgdef* msg_type =
1055
- envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab);
1191
+ envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(
1192
+ context.symtab);
1056
1193
  char buf[10240];
1057
1194
  upb_text_encode(cla, msg_type, nullptr, 0, buf, sizeof(buf));
1058
- gpr_log(GPR_DEBUG, "[xds_client %p] ClusterLoadAssignment: %s", client,
1059
- buf);
1195
+ gpr_log(GPR_DEBUG, "[xds_client %p] ClusterLoadAssignment: %s",
1196
+ context.client, buf);
1060
1197
  }
1061
1198
  }
1062
1199
 
1063
1200
  grpc_error* RoutePathMatchParse(const envoy_config_route_v3_RouteMatch* match,
1064
1201
  XdsApi::Route* route, bool* ignore_route) {
1065
- auto* case_sensitive = envoy_config_route_v3_RouteMatch_case_sensitive(match);
1066
- if (case_sensitive != nullptr) {
1067
- route->matchers.path_matcher.case_sensitive =
1068
- google_protobuf_BoolValue_value(case_sensitive);
1069
- }
1202
+ auto* case_sensitive_ptr =
1203
+ envoy_config_route_v3_RouteMatch_case_sensitive(match);
1204
+ bool case_sensitive = true;
1205
+ if (case_sensitive_ptr != nullptr) {
1206
+ case_sensitive = google_protobuf_BoolValue_value(case_sensitive_ptr);
1207
+ }
1208
+ StringMatcher::Type type;
1209
+ std::string match_string;
1070
1210
  if (envoy_config_route_v3_RouteMatch_has_prefix(match)) {
1071
1211
  absl::string_view prefix =
1072
1212
  UpbStringToAbsl(envoy_config_route_v3_RouteMatch_prefix(match));
@@ -1091,9 +1231,8 @@ grpc_error* RoutePathMatchParse(const envoy_config_route_v3_RouteMatch* match,
1091
1231
  return GRPC_ERROR_NONE;
1092
1232
  }
1093
1233
  }
1094
- route->matchers.path_matcher.type =
1095
- XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PREFIX;
1096
- route->matchers.path_matcher.string_matcher = std::string(prefix);
1234
+ type = StringMatcher::Type::PREFIX;
1235
+ match_string = std::string(prefix);
1097
1236
  } else if (envoy_config_route_v3_RouteMatch_has_path(match)) {
1098
1237
  absl::string_view path =
1099
1238
  UpbStringToAbsl(envoy_config_route_v3_RouteMatch_path(match));
@@ -1126,29 +1265,28 @@ grpc_error* RoutePathMatchParse(const envoy_config_route_v3_RouteMatch* match,
1126
1265
  *ignore_route = true;
1127
1266
  return GRPC_ERROR_NONE;
1128
1267
  }
1129
- route->matchers.path_matcher.type =
1130
- XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PATH;
1131
- route->matchers.path_matcher.string_matcher = std::string(path);
1268
+ type = StringMatcher::Type::EXACT;
1269
+ match_string = std::string(path);
1132
1270
  } else if (envoy_config_route_v3_RouteMatch_has_safe_regex(match)) {
1133
1271
  const envoy_type_matcher_v3_RegexMatcher* regex_matcher =
1134
1272
  envoy_config_route_v3_RouteMatch_safe_regex(match);
1135
1273
  GPR_ASSERT(regex_matcher != nullptr);
1136
- std::string matcher = UpbStringToStdString(
1274
+ type = StringMatcher::Type::SAFE_REGEX;
1275
+ match_string = UpbStringToStdString(
1137
1276
  envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher));
1138
- RE2::Options options;
1139
- options.set_case_sensitive(route->matchers.path_matcher.case_sensitive);
1140
- auto regex = absl::make_unique<RE2>(std::move(matcher), options);
1141
- if (!regex->ok()) {
1142
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1143
- "Invalid regex string specified in path matcher.");
1144
- }
1145
- route->matchers.path_matcher.type =
1146
- XdsApi::Route::Matchers::PathMatcher::PathMatcherType::REGEX;
1147
- route->matchers.path_matcher.regex_matcher = std::move(regex);
1148
1277
  } else {
1149
1278
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1150
1279
  "Invalid route path specifier specified.");
1151
1280
  }
1281
+ absl::StatusOr<StringMatcher> string_matcher =
1282
+ StringMatcher::Create(type, match_string, case_sensitive);
1283
+ if (!string_matcher.ok()) {
1284
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1285
+ absl::StrCat("path matcher: ", string_matcher.status().message())
1286
+ .c_str());
1287
+ ;
1288
+ }
1289
+ route->matchers.path_matcher = std::move(string_matcher.value());
1152
1290
  return GRPC_ERROR_NONE;
1153
1291
  }
1154
1292
 
@@ -1159,64 +1297,62 @@ grpc_error* RouteHeaderMatchersParse(
1159
1297
  envoy_config_route_v3_RouteMatch_headers(match, &size);
1160
1298
  for (size_t i = 0; i < size; ++i) {
1161
1299
  const envoy_config_route_v3_HeaderMatcher* header = headers[i];
1162
- XdsApi::Route::Matchers::HeaderMatcher header_matcher;
1163
- header_matcher.name =
1300
+ const std::string name =
1164
1301
  UpbStringToStdString(envoy_config_route_v3_HeaderMatcher_name(header));
1302
+ HeaderMatcher::Type type;
1303
+ std::string match_string;
1304
+ int64_t range_start = 0;
1305
+ int64_t range_end = 0;
1306
+ bool present_match = false;
1165
1307
  if (envoy_config_route_v3_HeaderMatcher_has_exact_match(header)) {
1166
- header_matcher.type =
1167
- XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::EXACT;
1168
- header_matcher.string_matcher = UpbStringToStdString(
1308
+ type = HeaderMatcher::Type::EXACT;
1309
+ match_string = UpbStringToStdString(
1169
1310
  envoy_config_route_v3_HeaderMatcher_exact_match(header));
1170
1311
  } else if (envoy_config_route_v3_HeaderMatcher_has_safe_regex_match(
1171
1312
  header)) {
1172
1313
  const envoy_type_matcher_v3_RegexMatcher* regex_matcher =
1173
1314
  envoy_config_route_v3_HeaderMatcher_safe_regex_match(header);
1174
1315
  GPR_ASSERT(regex_matcher != nullptr);
1175
- const std::string matcher = UpbStringToStdString(
1316
+ type = HeaderMatcher::Type::SAFE_REGEX;
1317
+ match_string = UpbStringToStdString(
1176
1318
  envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher));
1177
- std::unique_ptr<RE2> regex = absl::make_unique<RE2>(matcher);
1178
- if (!regex->ok()) {
1179
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1180
- "Invalid regex string specified in header matcher.");
1181
- }
1182
- header_matcher.type =
1183
- XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::REGEX;
1184
- header_matcher.regex_match = std::move(regex);
1185
1319
  } else if (envoy_config_route_v3_HeaderMatcher_has_range_match(header)) {
1186
- header_matcher.type =
1187
- XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::RANGE;
1320
+ type = HeaderMatcher::Type::RANGE;
1188
1321
  const envoy_type_v3_Int64Range* range_matcher =
1189
1322
  envoy_config_route_v3_HeaderMatcher_range_match(header);
1190
- header_matcher.range_start =
1191
- envoy_type_v3_Int64Range_start(range_matcher);
1192
- header_matcher.range_end = envoy_type_v3_Int64Range_end(range_matcher);
1193
- if (header_matcher.range_end < header_matcher.range_start) {
1194
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1195
- "Invalid range header matcher specifier specified: end "
1196
- "cannot be smaller than start.");
1197
- }
1323
+ range_start = envoy_type_v3_Int64Range_start(range_matcher);
1324
+ range_end = envoy_type_v3_Int64Range_end(range_matcher);
1198
1325
  } else if (envoy_config_route_v3_HeaderMatcher_has_present_match(header)) {
1199
- header_matcher.type =
1200
- XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PRESENT;
1201
- header_matcher.present_match =
1202
- envoy_config_route_v3_HeaderMatcher_present_match(header);
1326
+ type = HeaderMatcher::Type::PRESENT;
1327
+ present_match = envoy_config_route_v3_HeaderMatcher_present_match(header);
1203
1328
  } else if (envoy_config_route_v3_HeaderMatcher_has_prefix_match(header)) {
1204
- header_matcher.type =
1205
- XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PREFIX;
1206
- header_matcher.string_matcher = UpbStringToStdString(
1329
+ type = HeaderMatcher::Type::PREFIX;
1330
+ match_string = UpbStringToStdString(
1207
1331
  envoy_config_route_v3_HeaderMatcher_prefix_match(header));
1208
1332
  } else if (envoy_config_route_v3_HeaderMatcher_has_suffix_match(header)) {
1209
- header_matcher.type =
1210
- XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::SUFFIX;
1211
- header_matcher.string_matcher = UpbStringToStdString(
1333
+ type = HeaderMatcher::Type::SUFFIX;
1334
+ match_string = UpbStringToStdString(
1212
1335
  envoy_config_route_v3_HeaderMatcher_suffix_match(header));
1336
+ } else if (envoy_config_route_v3_HeaderMatcher_has_contains_match(header)) {
1337
+ type = HeaderMatcher::Type::CONTAINS;
1338
+ match_string = UpbStringToStdString(
1339
+ envoy_config_route_v3_HeaderMatcher_contains_match(header));
1213
1340
  } else {
1214
1341
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1215
1342
  "Invalid route header matcher specified.");
1216
1343
  }
1217
- header_matcher.invert_match =
1344
+ bool invert_match =
1218
1345
  envoy_config_route_v3_HeaderMatcher_invert_match(header);
1219
- route->matchers.header_matchers.emplace_back(std::move(header_matcher));
1346
+ absl::StatusOr<HeaderMatcher> header_matcher =
1347
+ HeaderMatcher::Create(name, type, match_string, range_start, range_end,
1348
+ present_match, invert_match);
1349
+ if (!header_matcher.ok()) {
1350
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1351
+ absl::StrCat("header matcher: ", header_matcher.status().message())
1352
+ .c_str());
1353
+ }
1354
+ route->matchers.header_matchers.emplace_back(
1355
+ std::move(header_matcher.value()));
1220
1356
  }
1221
1357
  return GRPC_ERROR_NONE;
1222
1358
  }
@@ -1254,7 +1390,96 @@ grpc_error* RouteRuntimeFractionParse(
1254
1390
  return GRPC_ERROR_NONE;
1255
1391
  }
1256
1392
 
1257
- grpc_error* RouteActionParse(const envoy_config_route_v3_Route* route_msg,
1393
+ grpc_error* ExtractHttpFilterTypeName(const EncodingContext& context,
1394
+ const google_protobuf_Any* any,
1395
+ absl::string_view* filter_type) {
1396
+ *filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any));
1397
+ if (*filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") {
1398
+ upb_strview any_value = google_protobuf_Any_value(any);
1399
+ const auto* typed_struct = udpa_type_v1_TypedStruct_parse(
1400
+ any_value.data, any_value.size, context.arena);
1401
+ if (typed_struct == nullptr) {
1402
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1403
+ "could not parse TypedStruct from filter config");
1404
+ }
1405
+ *filter_type =
1406
+ UpbStringToAbsl(udpa_type_v1_TypedStruct_type_url(typed_struct));
1407
+ }
1408
+ *filter_type = absl::StripPrefix(*filter_type, "type.googleapis.com/");
1409
+ return GRPC_ERROR_NONE;
1410
+ }
1411
+
1412
+ template <typename ParentType, typename EntryType>
1413
+ grpc_error* ParseTypedPerFilterConfig(
1414
+ const EncodingContext& context, const ParentType* parent,
1415
+ const EntryType* (*entry_func)(const ParentType*, size_t*),
1416
+ upb_strview (*key_func)(const EntryType*),
1417
+ const google_protobuf_Any* (*value_func)(const EntryType*),
1418
+ XdsApi::TypedPerFilterConfig* typed_per_filter_config) {
1419
+ size_t filter_it = UPB_MAP_BEGIN;
1420
+ while (true) {
1421
+ const auto* filter_entry = entry_func(parent, &filter_it);
1422
+ if (filter_entry == nullptr) break;
1423
+ absl::string_view key = UpbStringToAbsl(key_func(filter_entry));
1424
+ if (key.empty()) {
1425
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("empty filter name in map");
1426
+ }
1427
+ const google_protobuf_Any* any = value_func(filter_entry);
1428
+ GPR_ASSERT(any != nullptr);
1429
+ absl::string_view filter_type =
1430
+ UpbStringToAbsl(google_protobuf_Any_type_url(any));
1431
+ if (filter_type.empty()) {
1432
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1433
+ absl::StrCat("no filter config specified for filter name ", key)
1434
+ .c_str());
1435
+ }
1436
+ bool is_optional = false;
1437
+ if (filter_type ==
1438
+ "type.googleapis.com/envoy.config.route.v3.FilterConfig") {
1439
+ upb_strview any_value = google_protobuf_Any_value(any);
1440
+ const auto* filter_config = envoy_config_route_v3_FilterConfig_parse(
1441
+ any_value.data, any_value.size, context.arena);
1442
+ if (filter_config == nullptr) {
1443
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1444
+ absl::StrCat("could not parse FilterConfig wrapper for ", key)
1445
+ .c_str());
1446
+ }
1447
+ is_optional =
1448
+ envoy_config_route_v3_FilterConfig_is_optional(filter_config);
1449
+ any = envoy_config_route_v3_FilterConfig_config(filter_config);
1450
+ if (any == nullptr) {
1451
+ if (is_optional) continue;
1452
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1453
+ absl::StrCat("no filter config specified for filter name ", key)
1454
+ .c_str());
1455
+ }
1456
+ }
1457
+ grpc_error* error = ExtractHttpFilterTypeName(context, any, &filter_type);
1458
+ if (error != GRPC_ERROR_NONE) return error;
1459
+ const XdsHttpFilterImpl* filter_impl =
1460
+ XdsHttpFilterRegistry::GetFilterForType(filter_type);
1461
+ if (filter_impl == nullptr) {
1462
+ if (is_optional) continue;
1463
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1464
+ absl::StrCat("no filter registered for config type ", filter_type)
1465
+ .c_str());
1466
+ }
1467
+ absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config =
1468
+ filter_impl->GenerateFilterConfigOverride(
1469
+ google_protobuf_Any_value(any), context.arena);
1470
+ if (!filter_config.ok()) {
1471
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1472
+ absl::StrCat("filter config for type ", filter_type,
1473
+ " failed to parse: ", filter_config.status().ToString())
1474
+ .c_str());
1475
+ }
1476
+ (*typed_per_filter_config)[std::string(key)] = std::move(*filter_config);
1477
+ }
1478
+ return GRPC_ERROR_NONE;
1479
+ }
1480
+
1481
+ grpc_error* RouteActionParse(const EncodingContext& context,
1482
+ const envoy_config_route_v3_Route* route_msg,
1258
1483
  XdsApi::Route* route, bool* ignore_route) {
1259
1484
  if (!envoy_config_route_v3_Route_has_route(route_msg)) {
1260
1485
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@@ -1307,6 +1532,17 @@ grpc_error* RouteActionParse(const envoy_config_route_v3_Route* route_msg,
1307
1532
  cluster.weight = google_protobuf_UInt32Value_value(weight);
1308
1533
  if (cluster.weight == 0) continue;
1309
1534
  sum_of_weights += cluster.weight;
1535
+ if (context.use_v3) {
1536
+ grpc_error* error = ParseTypedPerFilterConfig<
1537
+ envoy_config_route_v3_WeightedCluster_ClusterWeight,
1538
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry>(
1539
+ context, cluster_weight,
1540
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_typed_per_filter_config_next,
1541
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_key,
1542
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_value,
1543
+ &cluster.typed_per_filter_config);
1544
+ if (error != GRPC_ERROR_NONE) return error;
1545
+ }
1310
1546
  route->weighted_clusters.emplace_back(std::move(cluster));
1311
1547
  }
1312
1548
  if (total_weight != sum_of_weights) {
@@ -1321,7 +1557,7 @@ grpc_error* RouteActionParse(const envoy_config_route_v3_Route* route_msg,
1321
1557
  // No cluster or weighted_clusters found in RouteAction, ignore this route.
1322
1558
  *ignore_route = true;
1323
1559
  }
1324
- if (XdsTimeoutEnabled() && !*ignore_route) {
1560
+ if (!*ignore_route) {
1325
1561
  const envoy_config_route_v3_RouteAction_MaxStreamDuration*
1326
1562
  max_stream_duration =
1327
1563
  envoy_config_route_v3_RouteAction_max_stream_duration(route_action);
@@ -1342,20 +1578,102 @@ grpc_error* RouteActionParse(const envoy_config_route_v3_Route* route_msg,
1342
1578
  }
1343
1579
  }
1344
1580
  }
1345
- return GRPC_ERROR_NONE;
1346
- }
1347
-
1348
- grpc_error* RouteConfigParse(
1349
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1350
- const envoy_config_route_v3_RouteConfiguration* route_config,
1351
- XdsApi::RdsUpdate* rds_update) {
1352
- MaybeLogRouteConfiguration(client, tracer, symtab, route_config);
1581
+ // Get HashPolicy from RouteAction
1582
+ if (XdsRingHashEnabled()) {
1583
+ size_t size = 0;
1584
+ const envoy_config_route_v3_RouteAction_HashPolicy* const* hash_policies =
1585
+ envoy_config_route_v3_RouteAction_hash_policy(route_action, &size);
1586
+ for (size_t i = 0; i < size; ++i) {
1587
+ const envoy_config_route_v3_RouteAction_HashPolicy* hash_policy =
1588
+ hash_policies[i];
1589
+ XdsApi::Route::HashPolicy policy;
1590
+ policy.terminal =
1591
+ envoy_config_route_v3_RouteAction_HashPolicy_terminal(hash_policy);
1592
+ const envoy_config_route_v3_RouteAction_HashPolicy_Header* header;
1593
+ const envoy_config_route_v3_RouteAction_HashPolicy_FilterState*
1594
+ filter_state;
1595
+ if ((header = envoy_config_route_v3_RouteAction_HashPolicy_header(
1596
+ hash_policy)) != nullptr) {
1597
+ policy.type = XdsApi::Route::HashPolicy::Type::HEADER;
1598
+ policy.header_name = UpbStringToStdString(
1599
+ envoy_config_route_v3_RouteAction_HashPolicy_Header_header_name(
1600
+ header));
1601
+ const struct envoy_type_matcher_v3_RegexMatchAndSubstitute*
1602
+ regex_rewrite =
1603
+ envoy_config_route_v3_RouteAction_HashPolicy_Header_regex_rewrite(
1604
+ header);
1605
+ if (regex_rewrite == nullptr) {
1606
+ gpr_log(
1607
+ GPR_DEBUG,
1608
+ "RouteAction HashPolicy contains policy specifier Header with "
1609
+ "RegexMatchAndSubstitution but Regex is missing");
1610
+ continue;
1611
+ }
1612
+ const envoy_type_matcher_v3_RegexMatcher* regex_matcher =
1613
+ envoy_type_matcher_v3_RegexMatchAndSubstitute_pattern(
1614
+ regex_rewrite);
1615
+ if (regex_matcher == nullptr) {
1616
+ gpr_log(
1617
+ GPR_DEBUG,
1618
+ "RouteAction HashPolicy contains policy specifier Header with "
1619
+ "RegexMatchAndSubstitution but RegexMatcher pattern is "
1620
+ "missing");
1621
+ continue;
1622
+ }
1623
+ RE2::Options options;
1624
+ policy.regex = absl::make_unique<RE2>(
1625
+ UpbStringToStdString(
1626
+ envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)),
1627
+ options);
1628
+ if (!policy.regex->ok()) {
1629
+ gpr_log(
1630
+ GPR_DEBUG,
1631
+ "RouteAction HashPolicy contains policy specifier Header with "
1632
+ "RegexMatchAndSubstitution but RegexMatcher pattern does not "
1633
+ "compile");
1634
+ continue;
1635
+ }
1636
+ policy.regex_substitution = UpbStringToStdString(
1637
+ envoy_type_matcher_v3_RegexMatchAndSubstitute_substitution(
1638
+ regex_rewrite));
1639
+ } else if ((filter_state =
1640
+ envoy_config_route_v3_RouteAction_HashPolicy_filter_state(
1641
+ hash_policy)) != nullptr) {
1642
+ std::string key = UpbStringToStdString(
1643
+ envoy_config_route_v3_RouteAction_HashPolicy_FilterState_key(
1644
+ filter_state));
1645
+ if (key == "io.grpc.channel_id") {
1646
+ policy.type = XdsApi::Route::HashPolicy::Type::CHANNEL_ID;
1647
+ } else {
1648
+ gpr_log(GPR_DEBUG,
1649
+ "RouteAction HashPolicy contains policy specifier "
1650
+ "FilterState but "
1651
+ "key is not io.grpc.channel_id.");
1652
+ continue;
1653
+ }
1654
+ } else {
1655
+ gpr_log(
1656
+ GPR_DEBUG,
1657
+ "RouteAction HashPolicy contains unsupported policy specifier.");
1658
+ continue;
1659
+ }
1660
+ route->hash_policies.emplace_back(std::move(policy));
1661
+ }
1662
+ }
1663
+ return GRPC_ERROR_NONE;
1664
+ }
1665
+
1666
+ grpc_error* RouteConfigParse(
1667
+ const EncodingContext& context,
1668
+ const envoy_config_route_v3_RouteConfiguration* route_config,
1669
+ XdsApi::RdsUpdate* rds_update) {
1670
+ MaybeLogRouteConfiguration(context, route_config);
1353
1671
  // Get the virtual hosts.
1354
- size_t size;
1672
+ size_t num_virtual_hosts;
1355
1673
  const envoy_config_route_v3_VirtualHost* const* virtual_hosts =
1356
- envoy_config_route_v3_RouteConfiguration_virtual_hosts(route_config,
1357
- &size);
1358
- for (size_t i = 0; i < size; ++i) {
1674
+ envoy_config_route_v3_RouteConfiguration_virtual_hosts(
1675
+ route_config, &num_virtual_hosts);
1676
+ for (size_t i = 0; i < num_virtual_hosts; ++i) {
1359
1677
  rds_update->virtual_hosts.emplace_back();
1360
1678
  XdsApi::RdsUpdate::VirtualHost& vhost = rds_update->virtual_hosts.back();
1361
1679
  // Parse domains.
@@ -1375,6 +1693,18 @@ grpc_error* RouteConfigParse(
1375
1693
  if (vhost.domains.empty()) {
1376
1694
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING("VirtualHost has no domains");
1377
1695
  }
1696
+ // Parse typed_per_filter_config.
1697
+ if (context.use_v3) {
1698
+ grpc_error* error = ParseTypedPerFilterConfig<
1699
+ envoy_config_route_v3_VirtualHost,
1700
+ envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry>(
1701
+ context, virtual_hosts[i],
1702
+ envoy_config_route_v3_VirtualHost_typed_per_filter_config_next,
1703
+ envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_key,
1704
+ envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_value,
1705
+ &vhost.typed_per_filter_config);
1706
+ if (error != GRPC_ERROR_NONE) return error;
1707
+ }
1378
1708
  // Parse routes.
1379
1709
  size_t num_routes;
1380
1710
  const envoy_config_route_v3_Route* const* routes =
@@ -1387,6 +1717,9 @@ grpc_error* RouteConfigParse(
1387
1717
  for (size_t j = 0; j < num_routes; ++j) {
1388
1718
  const envoy_config_route_v3_RouteMatch* match =
1389
1719
  envoy_config_route_v3_Route_match(routes[j]);
1720
+ if (match == nullptr) {
1721
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Match can't be null.");
1722
+ }
1390
1723
  size_t query_parameters_size;
1391
1724
  static_cast<void>(envoy_config_route_v3_RouteMatch_query_parameters(
1392
1725
  match, &query_parameters_size));
@@ -1402,9 +1735,20 @@ grpc_error* RouteConfigParse(
1402
1735
  if (error != GRPC_ERROR_NONE) return error;
1403
1736
  error = RouteRuntimeFractionParse(match, &route);
1404
1737
  if (error != GRPC_ERROR_NONE) return error;
1405
- error = RouteActionParse(routes[j], &route, &ignore_route);
1738
+ error = RouteActionParse(context, routes[j], &route, &ignore_route);
1406
1739
  if (error != GRPC_ERROR_NONE) return error;
1407
1740
  if (ignore_route) continue;
1741
+ if (context.use_v3) {
1742
+ grpc_error* error = ParseTypedPerFilterConfig<
1743
+ envoy_config_route_v3_Route,
1744
+ envoy_config_route_v3_Route_TypedPerFilterConfigEntry>(
1745
+ context, routes[j],
1746
+ envoy_config_route_v3_Route_typed_per_filter_config_next,
1747
+ envoy_config_route_v3_Route_TypedPerFilterConfigEntry_key,
1748
+ envoy_config_route_v3_Route_TypedPerFilterConfigEntry_value,
1749
+ &route.typed_per_filter_config);
1750
+ if (error != GRPC_ERROR_NONE) return error;
1751
+ }
1408
1752
  vhost.routes.emplace_back(std::move(route));
1409
1753
  }
1410
1754
  if (vhost.routes.empty()) {
@@ -1414,170 +1758,6 @@ grpc_error* RouteConfigParse(
1414
1758
  return GRPC_ERROR_NONE;
1415
1759
  }
1416
1760
 
1417
- grpc_error* LdsResponseParse(
1418
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1419
- const envoy_service_discovery_v3_DiscoveryResponse* response,
1420
- const std::set<absl::string_view>& expected_listener_names,
1421
- XdsApi::LdsUpdateMap* lds_update_map, upb_arena* arena) {
1422
- // Get the resources from the response.
1423
- size_t size;
1424
- const google_protobuf_Any* const* resources =
1425
- envoy_service_discovery_v3_DiscoveryResponse_resources(response, &size);
1426
- for (size_t i = 0; i < size; ++i) {
1427
- // Check the type_url of the resource.
1428
- absl::string_view type_url =
1429
- UpbStringToAbsl(google_protobuf_Any_type_url(resources[i]));
1430
- if (!IsLds(type_url)) {
1431
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not LDS.");
1432
- }
1433
- // Decode the listener.
1434
- const upb_strview encoded_listener =
1435
- google_protobuf_Any_value(resources[i]);
1436
- const envoy_config_listener_v3_Listener* listener =
1437
- envoy_config_listener_v3_Listener_parse(encoded_listener.data,
1438
- encoded_listener.size, arena);
1439
- if (listener == nullptr) {
1440
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode listener.");
1441
- }
1442
- // Check listener name. Ignore unexpected listeners.
1443
- std::string listener_name =
1444
- UpbStringToStdString(envoy_config_listener_v3_Listener_name(listener));
1445
- if (expected_listener_names.find(listener_name) ==
1446
- expected_listener_names.end()) {
1447
- continue;
1448
- }
1449
- // Fail if listener name is duplicated.
1450
- if (lds_update_map->find(listener_name) != lds_update_map->end()) {
1451
- return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1452
- absl::StrCat("duplicate listener name \"", listener_name, "\"")
1453
- .c_str());
1454
- }
1455
- XdsApi::LdsUpdate& lds_update = (*lds_update_map)[listener_name];
1456
- // Get api_listener and decode it to http_connection_manager.
1457
- const envoy_config_listener_v3_ApiListener* api_listener =
1458
- envoy_config_listener_v3_Listener_api_listener(listener);
1459
- if (api_listener == nullptr) {
1460
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1461
- "Listener has no ApiListener.");
1462
- }
1463
- const upb_strview encoded_api_listener = google_protobuf_Any_value(
1464
- envoy_config_listener_v3_ApiListener_api_listener(api_listener));
1465
- const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager*
1466
- http_connection_manager =
1467
- envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse(
1468
- encoded_api_listener.data, encoded_api_listener.size, arena);
1469
- if (http_connection_manager == nullptr) {
1470
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1471
- "Could not parse HttpConnectionManager config from ApiListener");
1472
- }
1473
- if (XdsTimeoutEnabled()) {
1474
- // Obtain max_stream_duration from Http Protocol Options.
1475
- const envoy_config_core_v3_HttpProtocolOptions* options =
1476
- envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_common_http_protocol_options(
1477
- http_connection_manager);
1478
- if (options != nullptr) {
1479
- const google_protobuf_Duration* duration =
1480
- envoy_config_core_v3_HttpProtocolOptions_max_stream_duration(
1481
- options);
1482
- if (duration != nullptr) {
1483
- lds_update.http_max_stream_duration.seconds =
1484
- google_protobuf_Duration_seconds(duration);
1485
- lds_update.http_max_stream_duration.nanos =
1486
- google_protobuf_Duration_nanos(duration);
1487
- }
1488
- }
1489
- }
1490
- // Found inlined route_config. Parse it to find the cluster_name.
1491
- if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config(
1492
- http_connection_manager)) {
1493
- const envoy_config_route_v3_RouteConfiguration* route_config =
1494
- envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_config(
1495
- http_connection_manager);
1496
- XdsApi::RdsUpdate rds_update;
1497
- grpc_error* error =
1498
- RouteConfigParse(client, tracer, symtab, route_config, &rds_update);
1499
- if (error != GRPC_ERROR_NONE) return error;
1500
- lds_update.rds_update = std::move(rds_update);
1501
- continue;
1502
- }
1503
- // Validate that RDS must be used to get the route_config dynamically.
1504
- if (!envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_rds(
1505
- http_connection_manager)) {
1506
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1507
- "HttpConnectionManager neither has inlined route_config nor RDS.");
1508
- }
1509
- const envoy_extensions_filters_network_http_connection_manager_v3_Rds* rds =
1510
- envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_rds(
1511
- http_connection_manager);
1512
- // Check that the ConfigSource specifies ADS.
1513
- const envoy_config_core_v3_ConfigSource* config_source =
1514
- envoy_extensions_filters_network_http_connection_manager_v3_Rds_config_source(
1515
- rds);
1516
- if (config_source == nullptr) {
1517
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1518
- "HttpConnectionManager missing config_source for RDS.");
1519
- }
1520
- if (!envoy_config_core_v3_ConfigSource_has_ads(config_source)) {
1521
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1522
- "HttpConnectionManager ConfigSource for RDS does not specify ADS.");
1523
- }
1524
- // Get the route_config_name.
1525
- lds_update.route_config_name = UpbStringToStdString(
1526
- envoy_extensions_filters_network_http_connection_manager_v3_Rds_route_config_name(
1527
- rds));
1528
- }
1529
- return GRPC_ERROR_NONE;
1530
- }
1531
-
1532
- grpc_error* RdsResponseParse(
1533
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
1534
- const envoy_service_discovery_v3_DiscoveryResponse* response,
1535
- const std::set<absl::string_view>& expected_route_configuration_names,
1536
- XdsApi::RdsUpdateMap* rds_update_map, upb_arena* arena) {
1537
- // Get the resources from the response.
1538
- size_t size;
1539
- const google_protobuf_Any* const* resources =
1540
- envoy_service_discovery_v3_DiscoveryResponse_resources(response, &size);
1541
- for (size_t i = 0; i < size; ++i) {
1542
- // Check the type_url of the resource.
1543
- absl::string_view type_url =
1544
- UpbStringToAbsl(google_protobuf_Any_type_url(resources[i]));
1545
- if (!IsRds(type_url)) {
1546
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not RDS.");
1547
- }
1548
- // Decode the route_config.
1549
- const upb_strview encoded_route_config =
1550
- google_protobuf_Any_value(resources[i]);
1551
- const envoy_config_route_v3_RouteConfiguration* route_config =
1552
- envoy_config_route_v3_RouteConfiguration_parse(
1553
- encoded_route_config.data, encoded_route_config.size, arena);
1554
- if (route_config == nullptr) {
1555
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode route_config.");
1556
- }
1557
- // Check route_config_name. Ignore unexpected route_config.
1558
- std::string route_config_name = UpbStringToStdString(
1559
- envoy_config_route_v3_RouteConfiguration_name(route_config));
1560
- if (expected_route_configuration_names.find(route_config_name) ==
1561
- expected_route_configuration_names.end()) {
1562
- continue;
1563
- }
1564
- // Fail if route config name is duplicated.
1565
- if (rds_update_map->find(route_config_name) != rds_update_map->end()) {
1566
- return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1567
- absl::StrCat("duplicate route config name \"", route_config_name,
1568
- "\"")
1569
- .c_str());
1570
- }
1571
- // Parse the route_config.
1572
- XdsApi::RdsUpdate& rds_update =
1573
- (*rds_update_map)[std::move(route_config_name)];
1574
- grpc_error* error =
1575
- RouteConfigParse(client, tracer, symtab, route_config, &rds_update);
1576
- if (error != GRPC_ERROR_NONE) return error;
1577
- }
1578
- return GRPC_ERROR_NONE;
1579
- }
1580
-
1581
1761
  XdsApi::CommonTlsContext::CertificateProviderInstance
1582
1762
  CertificateProviderInstanceParse(
1583
1763
  const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance*
@@ -1612,35 +1792,35 @@ grpc_error* CommonTlsContextParse(
1612
1792
  envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_match_subject_alt_names(
1613
1793
  default_validation_context, &len);
1614
1794
  for (size_t i = 0; i < len; ++i) {
1615
- XdsApi::StringMatcher::StringMatcherType type;
1795
+ StringMatcher::Type type;
1616
1796
  std::string matcher;
1617
1797
  if (envoy_type_matcher_v3_StringMatcher_has_exact(
1618
1798
  subject_alt_names_matchers[i])) {
1619
- type = XdsApi::StringMatcher::StringMatcherType::EXACT;
1799
+ type = StringMatcher::Type::EXACT;
1620
1800
  matcher =
1621
1801
  UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_exact(
1622
1802
  subject_alt_names_matchers[i]));
1623
1803
  } else if (envoy_type_matcher_v3_StringMatcher_has_prefix(
1624
1804
  subject_alt_names_matchers[i])) {
1625
- type = XdsApi::StringMatcher::StringMatcherType::PREFIX;
1805
+ type = StringMatcher::Type::PREFIX;
1626
1806
  matcher =
1627
1807
  UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_prefix(
1628
1808
  subject_alt_names_matchers[i]));
1629
1809
  } else if (envoy_type_matcher_v3_StringMatcher_has_suffix(
1630
1810
  subject_alt_names_matchers[i])) {
1631
- type = XdsApi::StringMatcher::StringMatcherType::SUFFIX;
1811
+ type = StringMatcher::Type::SUFFIX;
1632
1812
  matcher =
1633
1813
  UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_suffix(
1634
1814
  subject_alt_names_matchers[i]));
1635
1815
  } else if (envoy_type_matcher_v3_StringMatcher_has_contains(
1636
1816
  subject_alt_names_matchers[i])) {
1637
- type = XdsApi::StringMatcher::StringMatcherType::CONTAINS;
1817
+ type = StringMatcher::Type::CONTAINS;
1638
1818
  matcher =
1639
1819
  UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_contains(
1640
1820
  subject_alt_names_matchers[i]));
1641
1821
  } else if (envoy_type_matcher_v3_StringMatcher_has_safe_regex(
1642
1822
  subject_alt_names_matchers[i])) {
1643
- type = XdsApi::StringMatcher::StringMatcherType::SAFE_REGEX;
1823
+ type = StringMatcher::Type::SAFE_REGEX;
1644
1824
  auto* regex_matcher = envoy_type_matcher_v3_StringMatcher_safe_regex(
1645
1825
  subject_alt_names_matchers[i]);
1646
1826
  matcher = UpbStringToStdString(
@@ -1651,20 +1831,22 @@ grpc_error* CommonTlsContextParse(
1651
1831
  }
1652
1832
  bool ignore_case = envoy_type_matcher_v3_StringMatcher_ignore_case(
1653
1833
  subject_alt_names_matchers[i]);
1654
- XdsApi::StringMatcher string_matcher(type, matcher, ignore_case);
1655
- if (type == XdsApi::StringMatcher::StringMatcherType::SAFE_REGEX) {
1656
- if (!string_matcher.regex_matcher()->ok()) {
1657
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1658
- "Invalid regex string specified in string matcher.");
1659
- }
1660
- if (ignore_case) {
1661
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1662
- "StringMatcher: ignore_case has no effect for SAFE_REGEX.");
1663
- }
1834
+ absl::StatusOr<StringMatcher> string_matcher =
1835
+ StringMatcher::Create(type, matcher,
1836
+ /*case_sensitive=*/!ignore_case);
1837
+ if (!string_matcher.ok()) {
1838
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1839
+ absl::StrCat("string matcher: ",
1840
+ string_matcher.status().message())
1841
+ .c_str());
1842
+ }
1843
+ if (type == StringMatcher::Type::SAFE_REGEX && ignore_case) {
1844
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1845
+ "StringMatcher: ignore_case has no effect for SAFE_REGEX.");
1664
1846
  }
1665
1847
  common_tls_context->combined_validation_context
1666
1848
  .default_validation_context.match_subject_alt_names.push_back(
1667
- std::move(string_matcher));
1849
+ std::move(string_matcher.value()));
1668
1850
  }
1669
1851
  }
1670
1852
  auto* validation_context_certificate_provider_instance =
@@ -1688,11 +1870,793 @@ grpc_error* CommonTlsContextParse(
1688
1870
  return GRPC_ERROR_NONE;
1689
1871
  }
1690
1872
 
1873
+ grpc_error* HttpConnectionManagerParse(
1874
+ bool is_client, const EncodingContext& context,
1875
+ const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager*
1876
+ http_connection_manager_proto,
1877
+ bool is_v2,
1878
+ XdsApi::LdsUpdate::HttpConnectionManager* http_connection_manager) {
1879
+ MaybeLogHttpConnectionManager(context, http_connection_manager_proto);
1880
+ // Obtain max_stream_duration from Http Protocol Options.
1881
+ const envoy_config_core_v3_HttpProtocolOptions* options =
1882
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_common_http_protocol_options(
1883
+ http_connection_manager_proto);
1884
+ if (options != nullptr) {
1885
+ const google_protobuf_Duration* duration =
1886
+ envoy_config_core_v3_HttpProtocolOptions_max_stream_duration(options);
1887
+ if (duration != nullptr) {
1888
+ http_connection_manager->http_max_stream_duration.seconds =
1889
+ google_protobuf_Duration_seconds(duration);
1890
+ http_connection_manager->http_max_stream_duration.nanos =
1891
+ google_protobuf_Duration_nanos(duration);
1892
+ }
1893
+ }
1894
+ // Parse filters.
1895
+ if (!is_v2) {
1896
+ size_t num_filters = 0;
1897
+ const auto* http_filters =
1898
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_http_filters(
1899
+ http_connection_manager_proto, &num_filters);
1900
+ std::set<absl::string_view> names_seen;
1901
+ for (size_t i = 0; i < num_filters; ++i) {
1902
+ const auto* http_filter = http_filters[i];
1903
+ absl::string_view name = UpbStringToAbsl(
1904
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_name(
1905
+ http_filter));
1906
+ if (name.empty()) {
1907
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1908
+ absl::StrCat("empty filter name at index ", i).c_str());
1909
+ }
1910
+ if (names_seen.find(name) != names_seen.end()) {
1911
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1912
+ absl::StrCat("duplicate HTTP filter name: ", name).c_str());
1913
+ }
1914
+ names_seen.insert(name);
1915
+ const bool is_optional =
1916
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_is_optional(
1917
+ http_filter);
1918
+ const google_protobuf_Any* any =
1919
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_typed_config(
1920
+ http_filter);
1921
+ if (any == nullptr) {
1922
+ if (is_optional) continue;
1923
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1924
+ absl::StrCat("no filter config specified for filter name ", name)
1925
+ .c_str());
1926
+ }
1927
+ absl::string_view filter_type;
1928
+ grpc_error* error = ExtractHttpFilterTypeName(context, any, &filter_type);
1929
+ if (error != GRPC_ERROR_NONE) return error;
1930
+ const XdsHttpFilterImpl* filter_impl =
1931
+ XdsHttpFilterRegistry::GetFilterForType(filter_type);
1932
+ if (filter_impl == nullptr) {
1933
+ if (is_optional) continue;
1934
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1935
+ absl::StrCat("no filter registered for config type ", filter_type)
1936
+ .c_str());
1937
+ }
1938
+ if ((is_client && !filter_impl->IsSupportedOnClients()) ||
1939
+ (!is_client && !filter_impl->IsSupportedOnServers())) {
1940
+ if (is_optional) continue;
1941
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1942
+ absl::StrFormat("Filter %s is not supported on %s", filter_type,
1943
+ is_client ? "clients" : "servers")
1944
+ .c_str());
1945
+ }
1946
+ absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config =
1947
+ filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any),
1948
+ context.arena);
1949
+ if (!filter_config.ok()) {
1950
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1951
+ absl::StrCat(
1952
+ "filter config for type ", filter_type,
1953
+ " failed to parse: ", filter_config.status().ToString())
1954
+ .c_str());
1955
+ }
1956
+ http_connection_manager->http_filters.emplace_back(
1957
+ XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{
1958
+ std::string(name), std::move(*filter_config)});
1959
+ }
1960
+ } else {
1961
+ // If using a v2 config, we just hard-code a list containing only the
1962
+ // router filter without actually looking at the config. This ensures
1963
+ // that the right thing happens in the xds resolver without having
1964
+ // to expose whether the resource we received was v2 or v3.
1965
+ http_connection_manager->http_filters.emplace_back(
1966
+ XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{
1967
+ "router", {kXdsHttpRouterFilterConfigName, Json()}});
1968
+ }
1969
+ if (is_client) {
1970
+ // Found inlined route_config. Parse it to find the cluster_name.
1971
+ if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config(
1972
+ http_connection_manager_proto)) {
1973
+ const envoy_config_route_v3_RouteConfiguration* route_config =
1974
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_config(
1975
+ http_connection_manager_proto);
1976
+ XdsApi::RdsUpdate rds_update;
1977
+ grpc_error* error = RouteConfigParse(context, route_config, &rds_update);
1978
+ if (error != GRPC_ERROR_NONE) return error;
1979
+ http_connection_manager->rds_update = std::move(rds_update);
1980
+ return GRPC_ERROR_NONE;
1981
+ }
1982
+ // Validate that RDS must be used to get the route_config dynamically.
1983
+ const envoy_extensions_filters_network_http_connection_manager_v3_Rds* rds =
1984
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_rds(
1985
+ http_connection_manager_proto);
1986
+ if (rds == nullptr) {
1987
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1988
+ "HttpConnectionManager neither has inlined route_config nor RDS.");
1989
+ }
1990
+ // Check that the ConfigSource specifies ADS.
1991
+ const envoy_config_core_v3_ConfigSource* config_source =
1992
+ envoy_extensions_filters_network_http_connection_manager_v3_Rds_config_source(
1993
+ rds);
1994
+ if (config_source == nullptr) {
1995
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1996
+ "HttpConnectionManager missing config_source for RDS.");
1997
+ }
1998
+ if (!envoy_config_core_v3_ConfigSource_has_ads(config_source)) {
1999
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2000
+ "HttpConnectionManager ConfigSource for RDS does not specify ADS.");
2001
+ }
2002
+ // Get the route_config_name.
2003
+ http_connection_manager->route_config_name = UpbStringToStdString(
2004
+ envoy_extensions_filters_network_http_connection_manager_v3_Rds_route_config_name(
2005
+ rds));
2006
+ }
2007
+ return GRPC_ERROR_NONE;
2008
+ }
2009
+
2010
+ grpc_error* LdsResponseParseClient(
2011
+ const EncodingContext& context,
2012
+ const envoy_config_listener_v3_ApiListener* api_listener, bool is_v2,
2013
+ XdsApi::LdsUpdate* lds_update) {
2014
+ lds_update->type = XdsApi::LdsUpdate::ListenerType::kHttpApiListener;
2015
+ const upb_strview encoded_api_listener = google_protobuf_Any_value(
2016
+ envoy_config_listener_v3_ApiListener_api_listener(api_listener));
2017
+ const auto* http_connection_manager =
2018
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse(
2019
+ encoded_api_listener.data, encoded_api_listener.size, context.arena);
2020
+ if (http_connection_manager == nullptr) {
2021
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2022
+ "Could not parse HttpConnectionManager config from ApiListener");
2023
+ }
2024
+ return HttpConnectionManagerParse(true /* is_client */, context,
2025
+ http_connection_manager, is_v2,
2026
+ &lds_update->http_connection_manager);
2027
+ }
2028
+
2029
+ grpc_error* DownstreamTlsContextParse(
2030
+ const EncodingContext& context,
2031
+ const envoy_config_core_v3_TransportSocket* transport_socket,
2032
+ XdsApi::DownstreamTlsContext* downstream_tls_context) {
2033
+ absl::string_view name = UpbStringToAbsl(
2034
+ envoy_config_core_v3_TransportSocket_name(transport_socket));
2035
+ if (name == "envoy.transport_sockets.tls") {
2036
+ auto* typed_config =
2037
+ envoy_config_core_v3_TransportSocket_typed_config(transport_socket);
2038
+ if (typed_config != nullptr) {
2039
+ const upb_strview encoded_downstream_tls_context =
2040
+ google_protobuf_Any_value(typed_config);
2041
+ auto* downstream_tls_context_proto =
2042
+ envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_parse(
2043
+ encoded_downstream_tls_context.data,
2044
+ encoded_downstream_tls_context.size, context.arena);
2045
+ if (downstream_tls_context_proto == nullptr) {
2046
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2047
+ "Can't decode downstream tls context.");
2048
+ }
2049
+ auto* common_tls_context =
2050
+ envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_common_tls_context(
2051
+ downstream_tls_context_proto);
2052
+ if (common_tls_context != nullptr) {
2053
+ grpc_error* error = CommonTlsContextParse(
2054
+ common_tls_context, &downstream_tls_context->common_tls_context);
2055
+ if (error != GRPC_ERROR_NONE) return error;
2056
+ }
2057
+ auto* require_client_certificate =
2058
+ envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_require_client_certificate(
2059
+ downstream_tls_context_proto);
2060
+ if (require_client_certificate != nullptr) {
2061
+ downstream_tls_context->require_client_certificate =
2062
+ google_protobuf_BoolValue_value(require_client_certificate);
2063
+ }
2064
+ }
2065
+ if (downstream_tls_context->common_tls_context
2066
+ .tls_certificate_certificate_provider_instance.instance_name
2067
+ .empty()) {
2068
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2069
+ "TLS configuration provided but no "
2070
+ "tls_certificate_certificate_provider_instance found.");
2071
+ }
2072
+ }
2073
+ return GRPC_ERROR_NONE;
2074
+ }
2075
+
2076
+ grpc_error* CidrRangeParse(
2077
+ const envoy_config_core_v3_CidrRange* cidr_range_proto,
2078
+ XdsApi::LdsUpdate::FilterChainMap::CidrRange* cidr_range) {
2079
+ std::string address_prefix = UpbStringToStdString(
2080
+ envoy_config_core_v3_CidrRange_address_prefix(cidr_range_proto));
2081
+ grpc_error* error = grpc_string_to_sockaddr_new(&cidr_range->address,
2082
+ address_prefix.c_str(), 0);
2083
+ if (error != GRPC_ERROR_NONE) return error;
2084
+ cidr_range->prefix_len = 0;
2085
+ auto* prefix_len_proto =
2086
+ envoy_config_core_v3_CidrRange_prefix_len(cidr_range_proto);
2087
+ if (prefix_len_proto != nullptr) {
2088
+ cidr_range->prefix_len = std::min(
2089
+ google_protobuf_UInt32Value_value(prefix_len_proto),
2090
+ (reinterpret_cast<const grpc_sockaddr*>(cidr_range->address.addr))
2091
+ ->sa_family == GRPC_AF_INET
2092
+ ? uint32_t(32)
2093
+ : uint32_t(128));
2094
+ }
2095
+ // Normalize the network address by masking it with prefix_len
2096
+ grpc_sockaddr_mask_bits(&cidr_range->address, cidr_range->prefix_len);
2097
+ return GRPC_ERROR_NONE;
2098
+ }
2099
+
2100
+ grpc_error* FilterChainMatchParse(
2101
+ const envoy_config_listener_v3_FilterChainMatch* filter_chain_match_proto,
2102
+ FilterChain::FilterChainMatch* filter_chain_match) {
2103
+ auto* destination_port =
2104
+ envoy_config_listener_v3_FilterChainMatch_destination_port(
2105
+ filter_chain_match_proto);
2106
+ if (destination_port != nullptr) {
2107
+ filter_chain_match->destination_port =
2108
+ google_protobuf_UInt32Value_value(destination_port);
2109
+ }
2110
+ size_t size = 0;
2111
+ auto* prefix_ranges = envoy_config_listener_v3_FilterChainMatch_prefix_ranges(
2112
+ filter_chain_match_proto, &size);
2113
+ filter_chain_match->prefix_ranges.reserve(size);
2114
+ for (size_t i = 0; i < size; i++) {
2115
+ XdsApi::LdsUpdate::FilterChainMap::CidrRange cidr_range;
2116
+ grpc_error* error = CidrRangeParse(prefix_ranges[i], &cidr_range);
2117
+ if (error != GRPC_ERROR_NONE) return error;
2118
+ filter_chain_match->prefix_ranges.push_back(cidr_range);
2119
+ }
2120
+ filter_chain_match->source_type =
2121
+ static_cast<XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType>(
2122
+ envoy_config_listener_v3_FilterChainMatch_source_type(
2123
+ filter_chain_match_proto));
2124
+ auto* source_prefix_ranges =
2125
+ envoy_config_listener_v3_FilterChainMatch_source_prefix_ranges(
2126
+ filter_chain_match_proto, &size);
2127
+ filter_chain_match->source_prefix_ranges.reserve(size);
2128
+ for (size_t i = 0; i < size; i++) {
2129
+ XdsApi::LdsUpdate::FilterChainMap::CidrRange cidr_range;
2130
+ grpc_error* error = CidrRangeParse(source_prefix_ranges[i], &cidr_range);
2131
+ if (error != GRPC_ERROR_NONE) return error;
2132
+ filter_chain_match->source_prefix_ranges.push_back(cidr_range);
2133
+ }
2134
+ auto* source_ports = envoy_config_listener_v3_FilterChainMatch_source_ports(
2135
+ filter_chain_match_proto, &size);
2136
+ filter_chain_match->source_ports.reserve(size);
2137
+ for (size_t i = 0; i < size; i++) {
2138
+ filter_chain_match->source_ports.push_back(source_ports[i]);
2139
+ }
2140
+ auto* server_names = envoy_config_listener_v3_FilterChainMatch_server_names(
2141
+ filter_chain_match_proto, &size);
2142
+ for (size_t i = 0; i < size; i++) {
2143
+ filter_chain_match->server_names.push_back(
2144
+ UpbStringToStdString(server_names[i]));
2145
+ }
2146
+ filter_chain_match->transport_protocol = UpbStringToStdString(
2147
+ envoy_config_listener_v3_FilterChainMatch_transport_protocol(
2148
+ filter_chain_match_proto));
2149
+ auto* application_protocols =
2150
+ envoy_config_listener_v3_FilterChainMatch_application_protocols(
2151
+ filter_chain_match_proto, &size);
2152
+ for (size_t i = 0; i < size; i++) {
2153
+ filter_chain_match->application_protocols.push_back(
2154
+ UpbStringToStdString(application_protocols[i]));
2155
+ }
2156
+ return GRPC_ERROR_NONE;
2157
+ }
2158
+
2159
+ grpc_error* FilterChainParse(
2160
+ const EncodingContext& context,
2161
+ const envoy_config_listener_v3_FilterChain* filter_chain_proto, bool is_v2,
2162
+ FilterChain* filter_chain) {
2163
+ grpc_error* error = GRPC_ERROR_NONE;
2164
+ auto* filter_chain_match =
2165
+ envoy_config_listener_v3_FilterChain_filter_chain_match(
2166
+ filter_chain_proto);
2167
+ if (filter_chain_match != nullptr) {
2168
+ error = FilterChainMatchParse(filter_chain_match,
2169
+ &filter_chain->filter_chain_match);
2170
+ if (error != GRPC_ERROR_NONE) return error;
2171
+ }
2172
+ // Parse the filters list. Currently we only support HttpConnectionManager.
2173
+ size_t size = 0;
2174
+ auto* filters =
2175
+ envoy_config_listener_v3_FilterChain_filters(filter_chain_proto, &size);
2176
+ if (size != 1) {
2177
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2178
+ "FilterChain should have exactly one filter: HttpConnectionManager; no "
2179
+ "other filter is supported at the moment");
2180
+ }
2181
+ auto* typed_config = envoy_config_listener_v3_Filter_typed_config(filters[0]);
2182
+ if (typed_config == nullptr) {
2183
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2184
+ "No typed_config found in filter.");
2185
+ }
2186
+ absl::string_view type_url =
2187
+ UpbStringToAbsl(google_protobuf_Any_type_url(typed_config));
2188
+ if (type_url !=
2189
+ "type.googleapis.com/"
2190
+ "envoy.extensions.filters.network.http_connection_manager.v3."
2191
+ "HttpConnectionManager") {
2192
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2193
+ absl::StrCat("Unsupported filter type ", type_url).c_str());
2194
+ }
2195
+ const upb_strview encoded_http_connection_manager =
2196
+ google_protobuf_Any_value(typed_config);
2197
+ const auto* http_connection_manager =
2198
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse(
2199
+ encoded_http_connection_manager.data,
2200
+ encoded_http_connection_manager.size, context.arena);
2201
+ if (http_connection_manager == nullptr) {
2202
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2203
+ "Could not parse HttpConnectionManager config from filter "
2204
+ "typed_config");
2205
+ }
2206
+ filter_chain->filter_chain_data =
2207
+ std::make_shared<XdsApi::LdsUpdate::FilterChainData>();
2208
+ error = HttpConnectionManagerParse(
2209
+ false /* is_client */, context, http_connection_manager, is_v2,
2210
+ &filter_chain->filter_chain_data->http_connection_manager);
2211
+ if (error != GRPC_ERROR_NONE) return error;
2212
+ // Get the DownstreamTlsContext for the filter chain
2213
+ if (XdsSecurityEnabled()) {
2214
+ auto* transport_socket =
2215
+ envoy_config_listener_v3_FilterChain_transport_socket(
2216
+ filter_chain_proto);
2217
+ if (transport_socket != nullptr) {
2218
+ error = DownstreamTlsContextParse(
2219
+ context, transport_socket,
2220
+ &filter_chain->filter_chain_data->downstream_tls_context);
2221
+ }
2222
+ }
2223
+ return error;
2224
+ }
2225
+
2226
+ grpc_error* AddressParse(const envoy_config_core_v3_Address* address_proto,
2227
+ std::string* address) {
2228
+ const auto* socket_address =
2229
+ envoy_config_core_v3_Address_socket_address(address_proto);
2230
+ if (socket_address == nullptr) {
2231
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2232
+ "Address does not have socket_address");
2233
+ }
2234
+ if (envoy_config_core_v3_SocketAddress_protocol(socket_address) !=
2235
+ envoy_config_core_v3_SocketAddress_TCP) {
2236
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2237
+ "SocketAddress protocol is not TCP");
2238
+ }
2239
+ uint32_t port = envoy_config_core_v3_SocketAddress_port_value(socket_address);
2240
+ if (port > 65535) {
2241
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Invalid port");
2242
+ }
2243
+ *address = JoinHostPort(
2244
+ UpbStringToAbsl(
2245
+ envoy_config_core_v3_SocketAddress_address(socket_address)),
2246
+ port);
2247
+ return GRPC_ERROR_NONE;
2248
+ }
2249
+
2250
+ // An intermediate map for filter chains that we create to validate the list of
2251
+ // filter chains received from the control plane and to finally create
2252
+ // XdsApi::LdsUpdate::FilterChainMap
2253
+ struct InternalFilterChainMap {
2254
+ using SourceIpMap =
2255
+ std::map<std::string, XdsApi::LdsUpdate::FilterChainMap::SourceIp>;
2256
+ using ConnectionSourceTypesArray = std::array<SourceIpMap, 3>;
2257
+ struct DestinationIp {
2258
+ absl::optional<XdsApi::LdsUpdate::FilterChainMap::CidrRange> prefix_range;
2259
+ bool transport_protocol_raw_buffer_provided = false;
2260
+ ConnectionSourceTypesArray source_types_array;
2261
+ };
2262
+ using DestinationIpMap = std::map<std::string, DestinationIp>;
2263
+ DestinationIpMap destination_ip_map;
2264
+ };
2265
+
2266
+ grpc_error* AddFilterChainDataForSourcePort(
2267
+ const FilterChain& filter_chain,
2268
+ XdsApi::LdsUpdate::FilterChainMap::SourcePortsMap* ports_map,
2269
+ uint32_t port) {
2270
+ auto insert_result = ports_map->emplace(
2271
+ port, XdsApi::LdsUpdate::FilterChainMap::FilterChainDataSharedPtr{
2272
+ filter_chain.filter_chain_data});
2273
+ if (!insert_result.second) {
2274
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2275
+ absl::StrCat(
2276
+ "Duplicate matching rules detected when adding filter chain: ",
2277
+ filter_chain.filter_chain_match.ToString())
2278
+ .c_str());
2279
+ }
2280
+ return GRPC_ERROR_NONE;
2281
+ }
2282
+
2283
+ grpc_error* AddFilterChainDataForSourcePorts(
2284
+ const FilterChain& filter_chain,
2285
+ XdsApi::LdsUpdate::FilterChainMap::SourcePortsMap* ports_map) {
2286
+ if (filter_chain.filter_chain_match.source_ports.empty()) {
2287
+ return AddFilterChainDataForSourcePort(filter_chain, ports_map, 0);
2288
+ } else {
2289
+ for (uint32_t port : filter_chain.filter_chain_match.source_ports) {
2290
+ grpc_error* error =
2291
+ AddFilterChainDataForSourcePort(filter_chain, ports_map, port);
2292
+ if (error != GRPC_ERROR_NONE) return error;
2293
+ }
2294
+ }
2295
+ return GRPC_ERROR_NONE;
2296
+ }
2297
+
2298
+ grpc_error* AddFilterChainDataForSourceIpRange(
2299
+ const FilterChain& filter_chain,
2300
+ InternalFilterChainMap::SourceIpMap* source_ip_map) {
2301
+ if (filter_chain.filter_chain_match.source_prefix_ranges.empty()) {
2302
+ auto insert_result = source_ip_map->emplace(
2303
+ "", XdsApi::LdsUpdate::FilterChainMap::SourceIp());
2304
+ return AddFilterChainDataForSourcePorts(
2305
+ filter_chain, &insert_result.first->second.ports_map);
2306
+ } else {
2307
+ for (const auto& prefix_range :
2308
+ filter_chain.filter_chain_match.source_prefix_ranges) {
2309
+ auto insert_result = source_ip_map->emplace(
2310
+ absl::StrCat(grpc_sockaddr_to_string(&prefix_range.address, false),
2311
+ "/", prefix_range.prefix_len),
2312
+ XdsApi::LdsUpdate::FilterChainMap::SourceIp());
2313
+ if (insert_result.second) {
2314
+ insert_result.first->second.prefix_range.emplace(prefix_range);
2315
+ }
2316
+ grpc_error* error = AddFilterChainDataForSourcePorts(
2317
+ filter_chain, &insert_result.first->second.ports_map);
2318
+ if (error != GRPC_ERROR_NONE) return error;
2319
+ }
2320
+ }
2321
+ return GRPC_ERROR_NONE;
2322
+ }
2323
+
2324
+ grpc_error* AddFilterChainDataForSourceType(
2325
+ const FilterChain& filter_chain,
2326
+ InternalFilterChainMap::DestinationIp* destination_ip) {
2327
+ GPR_ASSERT(static_cast<unsigned int>(
2328
+ filter_chain.filter_chain_match.source_type) < 3);
2329
+ return AddFilterChainDataForSourceIpRange(
2330
+ filter_chain, &destination_ip->source_types_array[static_cast<int>(
2331
+ filter_chain.filter_chain_match.source_type)]);
2332
+ }
2333
+
2334
+ grpc_error* AddFilterChainDataForApplicationProtocols(
2335
+ const FilterChain& filter_chain,
2336
+ InternalFilterChainMap::DestinationIp* destination_ip) {
2337
+ // Only allow filter chains that do not mention application protocols
2338
+ if (!filter_chain.filter_chain_match.application_protocols.empty()) {
2339
+ return GRPC_ERROR_NONE;
2340
+ }
2341
+ return AddFilterChainDataForSourceType(filter_chain, destination_ip);
2342
+ }
2343
+
2344
+ grpc_error* AddFilterChainDataForTransportProtocol(
2345
+ const FilterChain& filter_chain,
2346
+ InternalFilterChainMap::DestinationIp* destination_ip) {
2347
+ const std::string& transport_protocol =
2348
+ filter_chain.filter_chain_match.transport_protocol;
2349
+ // Only allow filter chains with no transport protocol or "raw_buffer"
2350
+ if (!transport_protocol.empty() && transport_protocol != "raw_buffer") {
2351
+ return GRPC_ERROR_NONE;
2352
+ }
2353
+ // If for this configuration, we've already seen filter chains that mention
2354
+ // the transport protocol as "raw_buffer", we will never match filter chains
2355
+ // that do not mention it.
2356
+ if (destination_ip->transport_protocol_raw_buffer_provided &&
2357
+ transport_protocol.empty()) {
2358
+ return GRPC_ERROR_NONE;
2359
+ }
2360
+ if (!transport_protocol.empty() &&
2361
+ !destination_ip->transport_protocol_raw_buffer_provided) {
2362
+ destination_ip->transport_protocol_raw_buffer_provided = true;
2363
+ // Clear out the previous entries if any since those entries did not mention
2364
+ // "raw_buffer"
2365
+ destination_ip->source_types_array =
2366
+ InternalFilterChainMap::ConnectionSourceTypesArray();
2367
+ }
2368
+ return AddFilterChainDataForApplicationProtocols(filter_chain,
2369
+ destination_ip);
2370
+ }
2371
+
2372
+ grpc_error* AddFilterChainDataForServerNames(
2373
+ const FilterChain& filter_chain,
2374
+ InternalFilterChainMap::DestinationIp* destination_ip) {
2375
+ // Don't continue adding filter chains with server names mentioned
2376
+ if (!filter_chain.filter_chain_match.server_names.empty()) {
2377
+ return GRPC_ERROR_NONE;
2378
+ }
2379
+ return AddFilterChainDataForTransportProtocol(filter_chain, destination_ip);
2380
+ }
2381
+
2382
+ grpc_error* AddFilterChainDataForDestinationIpRange(
2383
+ const FilterChain& filter_chain,
2384
+ InternalFilterChainMap::DestinationIpMap* destination_ip_map) {
2385
+ if (filter_chain.filter_chain_match.prefix_ranges.empty()) {
2386
+ auto insert_result = destination_ip_map->emplace(
2387
+ "", InternalFilterChainMap::DestinationIp());
2388
+ return AddFilterChainDataForServerNames(filter_chain,
2389
+ &insert_result.first->second);
2390
+ } else {
2391
+ for (const auto& prefix_range :
2392
+ filter_chain.filter_chain_match.prefix_ranges) {
2393
+ auto insert_result = destination_ip_map->emplace(
2394
+ absl::StrCat(grpc_sockaddr_to_string(&prefix_range.address, false),
2395
+ "/", prefix_range.prefix_len),
2396
+ InternalFilterChainMap::DestinationIp());
2397
+ if (insert_result.second) {
2398
+ insert_result.first->second.prefix_range.emplace(prefix_range);
2399
+ }
2400
+ grpc_error* error = AddFilterChainDataForServerNames(
2401
+ filter_chain, &insert_result.first->second);
2402
+ if (error != GRPC_ERROR_NONE) return error;
2403
+ }
2404
+ }
2405
+ return GRPC_ERROR_NONE;
2406
+ }
2407
+
2408
+ XdsApi::LdsUpdate::FilterChainMap BuildFromInternalFilterChainMap(
2409
+ InternalFilterChainMap* internal_filter_chain_map) {
2410
+ XdsApi::LdsUpdate::FilterChainMap filter_chain_map;
2411
+ for (auto& destination_ip_pair :
2412
+ internal_filter_chain_map->destination_ip_map) {
2413
+ XdsApi::LdsUpdate::FilterChainMap::DestinationIp destination_ip;
2414
+ destination_ip.prefix_range = destination_ip_pair.second.prefix_range;
2415
+ for (int i = 0; i < 3; i++) {
2416
+ auto& source_ip_map = destination_ip_pair.second.source_types_array[i];
2417
+ for (auto& source_ip_pair : source_ip_map) {
2418
+ destination_ip.source_types_array[i].push_back(
2419
+ std::move(source_ip_pair.second));
2420
+ }
2421
+ }
2422
+ filter_chain_map.destination_ip_vector.push_back(std::move(destination_ip));
2423
+ }
2424
+ return filter_chain_map;
2425
+ }
2426
+
2427
+ grpc_error* BuildFilterChainMap(
2428
+ const std::vector<FilterChain>& filter_chains,
2429
+ XdsApi::LdsUpdate::FilterChainMap* filter_chain_map) {
2430
+ InternalFilterChainMap internal_filter_chain_map;
2431
+ for (const auto& filter_chain : filter_chains) {
2432
+ // Discard filter chain entries that specify destination port
2433
+ if (filter_chain.filter_chain_match.destination_port != 0) continue;
2434
+ grpc_error* error = AddFilterChainDataForDestinationIpRange(
2435
+ filter_chain, &internal_filter_chain_map.destination_ip_map);
2436
+ if (error != GRPC_ERROR_NONE) return error;
2437
+ }
2438
+ *filter_chain_map =
2439
+ BuildFromInternalFilterChainMap(&internal_filter_chain_map);
2440
+ return GRPC_ERROR_NONE;
2441
+ }
2442
+
2443
+ grpc_error* LdsResponseParseServer(
2444
+ const EncodingContext& context,
2445
+ const envoy_config_listener_v3_Listener* listener, bool is_v2,
2446
+ XdsApi::LdsUpdate* lds_update) {
2447
+ lds_update->type = XdsApi::LdsUpdate::ListenerType::kTcpListener;
2448
+ grpc_error* error =
2449
+ AddressParse(envoy_config_listener_v3_Listener_address(listener),
2450
+ &lds_update->address);
2451
+ if (error != GRPC_ERROR_NONE) return error;
2452
+ const auto* use_original_dst =
2453
+ envoy_config_listener_v3_Listener_use_original_dst(listener);
2454
+ if (use_original_dst != nullptr) {
2455
+ if (google_protobuf_BoolValue_value(use_original_dst)) {
2456
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2457
+ "Field \'use_original_dst\' is not supported.");
2458
+ }
2459
+ }
2460
+ size_t size = 0;
2461
+ auto* filter_chains =
2462
+ envoy_config_listener_v3_Listener_filter_chains(listener, &size);
2463
+ std::vector<FilterChain> parsed_filter_chains;
2464
+ parsed_filter_chains.reserve(size);
2465
+ for (size_t i = 0; i < size; i++) {
2466
+ FilterChain filter_chain;
2467
+ error = FilterChainParse(context, filter_chains[i], is_v2, &filter_chain);
2468
+ if (error != GRPC_ERROR_NONE) return error;
2469
+ parsed_filter_chains.push_back(std::move(filter_chain));
2470
+ }
2471
+ error =
2472
+ BuildFilterChainMap(parsed_filter_chains, &lds_update->filter_chain_map);
2473
+ if (error != GRPC_ERROR_NONE) return error;
2474
+ auto* default_filter_chain =
2475
+ envoy_config_listener_v3_Listener_default_filter_chain(listener);
2476
+ if (default_filter_chain != nullptr) {
2477
+ FilterChain filter_chain;
2478
+ error =
2479
+ FilterChainParse(context, default_filter_chain, is_v2, &filter_chain);
2480
+ if (error != GRPC_ERROR_NONE) return error;
2481
+ if (filter_chain.filter_chain_data != nullptr) {
2482
+ lds_update->default_filter_chain =
2483
+ std::move(*filter_chain.filter_chain_data);
2484
+ }
2485
+ }
2486
+ if (size == 0 && default_filter_chain == nullptr) {
2487
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No filter chain provided.");
2488
+ }
2489
+ return GRPC_ERROR_NONE;
2490
+ }
2491
+
2492
+ grpc_error* LdsResponseParse(
2493
+ const EncodingContext& context,
2494
+ const envoy_service_discovery_v3_DiscoveryResponse* response,
2495
+ const std::set<absl::string_view>& expected_listener_names,
2496
+ XdsApi::LdsUpdateMap* lds_update_map,
2497
+ std::set<std::string>* resource_names_failed) {
2498
+ std::vector<grpc_error*> errors;
2499
+ // Get the resources from the response.
2500
+ size_t size;
2501
+ const google_protobuf_Any* const* resources =
2502
+ envoy_service_discovery_v3_DiscoveryResponse_resources(response, &size);
2503
+ for (size_t i = 0; i < size; ++i) {
2504
+ // Check the type_url of the resource.
2505
+ absl::string_view type_url =
2506
+ UpbStringToAbsl(google_protobuf_Any_type_url(resources[i]));
2507
+ bool is_v2 = false;
2508
+ if (!IsLds(type_url, &is_v2)) {
2509
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2510
+ absl::StrCat("resource index ", i, ": Resource is not LDS.")
2511
+ .c_str()));
2512
+ continue;
2513
+ }
2514
+ // Decode the listener.
2515
+ const upb_strview encoded_listener =
2516
+ google_protobuf_Any_value(resources[i]);
2517
+ const envoy_config_listener_v3_Listener* listener =
2518
+ envoy_config_listener_v3_Listener_parse(
2519
+ encoded_listener.data, encoded_listener.size, context.arena);
2520
+ if (listener == nullptr) {
2521
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2522
+ absl::StrCat("resource index ", i, ": Can't decode listener.")
2523
+ .c_str()));
2524
+ continue;
2525
+ }
2526
+ // Check listener name. Ignore unexpected listeners.
2527
+ std::string listener_name =
2528
+ UpbStringToStdString(envoy_config_listener_v3_Listener_name(listener));
2529
+ if (expected_listener_names.find(listener_name) ==
2530
+ expected_listener_names.end()) {
2531
+ continue;
2532
+ }
2533
+ // Fail if listener name is duplicated.
2534
+ if (lds_update_map->find(listener_name) != lds_update_map->end()) {
2535
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2536
+ absl::StrCat("duplicate listener name \"", listener_name, "\"")
2537
+ .c_str()));
2538
+ resource_names_failed->insert(listener_name);
2539
+ continue;
2540
+ }
2541
+ // Serialize into JSON and store it in the LdsUpdateMap
2542
+ XdsApi::LdsResourceData& lds_resource_data =
2543
+ (*lds_update_map)[listener_name];
2544
+ XdsApi::LdsUpdate& lds_update = lds_resource_data.resource;
2545
+ lds_resource_data.serialized_proto = UpbStringToStdString(encoded_listener);
2546
+ // Check whether it's a client or server listener.
2547
+ const envoy_config_listener_v3_ApiListener* api_listener =
2548
+ envoy_config_listener_v3_Listener_api_listener(listener);
2549
+ const envoy_config_core_v3_Address* address =
2550
+ envoy_config_listener_v3_Listener_address(listener);
2551
+ if (api_listener != nullptr && address != nullptr) {
2552
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2553
+ absl::StrCat(listener_name,
2554
+ ": Listener has both address and ApiListener")
2555
+ .c_str()));
2556
+ resource_names_failed->insert(listener_name);
2557
+ continue;
2558
+ }
2559
+ if (api_listener == nullptr && address == nullptr) {
2560
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2561
+ absl::StrCat(listener_name,
2562
+ ": Listener has neither address nor ApiListener")
2563
+ .c_str()));
2564
+ resource_names_failed->insert(listener_name);
2565
+ continue;
2566
+ }
2567
+ grpc_error* error = GRPC_ERROR_NONE;
2568
+ if (api_listener != nullptr) {
2569
+ error = LdsResponseParseClient(context, api_listener, is_v2, &lds_update);
2570
+ } else {
2571
+ error = LdsResponseParseServer(context, listener, is_v2, &lds_update);
2572
+ }
2573
+ if (error != GRPC_ERROR_NONE) {
2574
+ errors.push_back(grpc_error_add_child(
2575
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2576
+ absl::StrCat(listener_name, ": validation error").c_str()),
2577
+ error));
2578
+ resource_names_failed->insert(listener_name);
2579
+ }
2580
+ }
2581
+ return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing LDS response", &errors);
2582
+ }
2583
+
2584
+ grpc_error* RdsResponseParse(
2585
+ const EncodingContext& context,
2586
+ const envoy_service_discovery_v3_DiscoveryResponse* response,
2587
+ const std::set<absl::string_view>& expected_route_configuration_names,
2588
+ XdsApi::RdsUpdateMap* rds_update_map,
2589
+ std::set<std::string>* resource_names_failed) {
2590
+ std::vector<grpc_error*> errors;
2591
+ // Get the resources from the response.
2592
+ size_t size;
2593
+ const google_protobuf_Any* const* resources =
2594
+ envoy_service_discovery_v3_DiscoveryResponse_resources(response, &size);
2595
+ for (size_t i = 0; i < size; ++i) {
2596
+ // Check the type_url of the resource.
2597
+ absl::string_view type_url =
2598
+ UpbStringToAbsl(google_protobuf_Any_type_url(resources[i]));
2599
+ if (!IsRds(type_url)) {
2600
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2601
+ absl::StrCat("resource index ", i, ": Resource is not RDS.")
2602
+ .c_str()));
2603
+ continue;
2604
+ }
2605
+ // Decode the route_config.
2606
+ const upb_strview encoded_route_config =
2607
+ google_protobuf_Any_value(resources[i]);
2608
+ const envoy_config_route_v3_RouteConfiguration* route_config =
2609
+ envoy_config_route_v3_RouteConfiguration_parse(
2610
+ encoded_route_config.data, encoded_route_config.size,
2611
+ context.arena);
2612
+ if (route_config == nullptr) {
2613
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2614
+ absl::StrCat("resource index ", i, ": Can't decode route_config.")
2615
+ .c_str()));
2616
+ continue;
2617
+ }
2618
+ // Check route_config_name. Ignore unexpected route_config.
2619
+ std::string route_config_name = UpbStringToStdString(
2620
+ envoy_config_route_v3_RouteConfiguration_name(route_config));
2621
+ if (expected_route_configuration_names.find(route_config_name) ==
2622
+ expected_route_configuration_names.end()) {
2623
+ continue;
2624
+ }
2625
+ // Fail if route config name is duplicated.
2626
+ if (rds_update_map->find(route_config_name) != rds_update_map->end()) {
2627
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2628
+ absl::StrCat("duplicate route config name \"", route_config_name,
2629
+ "\"")
2630
+ .c_str()));
2631
+ resource_names_failed->insert(route_config_name);
2632
+ continue;
2633
+ }
2634
+ // Serialize into JSON and store it in the RdsUpdateMap
2635
+ XdsApi::RdsResourceData& rds_resource_data =
2636
+ (*rds_update_map)[route_config_name];
2637
+ XdsApi::RdsUpdate& rds_update = rds_resource_data.resource;
2638
+ rds_resource_data.serialized_proto =
2639
+ UpbStringToStdString(encoded_route_config);
2640
+ // Parse the route_config.
2641
+ grpc_error* error = RouteConfigParse(context, route_config, &rds_update);
2642
+ if (error != GRPC_ERROR_NONE) {
2643
+ errors.push_back(grpc_error_add_child(
2644
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2645
+ absl::StrCat(route_config_name, ": validation error").c_str()),
2646
+ error));
2647
+ resource_names_failed->insert(route_config_name);
2648
+ }
2649
+ }
2650
+ return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing RDS response", &errors);
2651
+ }
2652
+
1691
2653
  grpc_error* CdsResponseParse(
1692
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
2654
+ const EncodingContext& context,
1693
2655
  const envoy_service_discovery_v3_DiscoveryResponse* response,
1694
2656
  const std::set<absl::string_view>& expected_cluster_names,
1695
- XdsApi::CdsUpdateMap* cds_update_map, upb_arena* arena) {
2657
+ XdsApi::CdsUpdateMap* cds_update_map,
2658
+ std::set<std::string>* resource_names_failed) {
2659
+ std::vector<grpc_error*> errors;
1696
2660
  // Get the resources from the response.
1697
2661
  size_t size;
1698
2662
  const google_protobuf_Any* const* resources =
@@ -1703,17 +2667,23 @@ grpc_error* CdsResponseParse(
1703
2667
  absl::string_view type_url =
1704
2668
  UpbStringToAbsl(google_protobuf_Any_type_url(resources[i]));
1705
2669
  if (!IsCds(type_url)) {
1706
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not CDS.");
2670
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2671
+ absl::StrCat("resource index ", i, ": Resource is not CDS.")
2672
+ .c_str()));
2673
+ continue;
1707
2674
  }
1708
2675
  // Decode the cluster.
1709
2676
  const upb_strview encoded_cluster = google_protobuf_Any_value(resources[i]);
1710
2677
  const envoy_config_cluster_v3_Cluster* cluster =
1711
- envoy_config_cluster_v3_Cluster_parse(encoded_cluster.data,
1712
- encoded_cluster.size, arena);
2678
+ envoy_config_cluster_v3_Cluster_parse(
2679
+ encoded_cluster.data, encoded_cluster.size, context.arena);
1713
2680
  if (cluster == nullptr) {
1714
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode cluster.");
2681
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2682
+ absl::StrCat("resource index ", i, ": Can't decode cluster.")
2683
+ .c_str()));
2684
+ continue;
1715
2685
  }
1716
- MaybeLogCluster(client, tracer, symtab, cluster);
2686
+ MaybeLogCluster(context, cluster);
1717
2687
  // Ignore unexpected cluster names.
1718
2688
  std::string cluster_name =
1719
2689
  UpbStringToStdString(envoy_config_cluster_v3_Cluster_name(cluster));
@@ -1723,41 +2693,194 @@ grpc_error* CdsResponseParse(
1723
2693
  }
1724
2694
  // Fail on duplicate resources.
1725
2695
  if (cds_update_map->find(cluster_name) != cds_update_map->end()) {
1726
- return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2696
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1727
2697
  absl::StrCat("duplicate resource name \"", cluster_name, "\"")
1728
- .c_str());
2698
+ .c_str()));
2699
+ resource_names_failed->insert(cluster_name);
2700
+ continue;
1729
2701
  }
1730
- XdsApi::CdsUpdate& cds_update = (*cds_update_map)[std::move(cluster_name)];
2702
+ // Serialize into JSON and store it in the CdsUpdateMap
2703
+ XdsApi::CdsResourceData& cds_resource_data =
2704
+ (*cds_update_map)[cluster_name];
2705
+ XdsApi::CdsUpdate& cds_update = cds_resource_data.resource;
2706
+ cds_resource_data.serialized_proto = UpbStringToStdString(encoded_cluster);
1731
2707
  // Check the cluster_discovery_type.
1732
- if (!envoy_config_cluster_v3_Cluster_has_type(cluster)) {
1733
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType not found.");
2708
+ if (!envoy_config_cluster_v3_Cluster_has_type(cluster) &&
2709
+ !envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) {
2710
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2711
+ absl::StrCat(cluster_name, ": DiscoveryType not found.").c_str()));
2712
+ resource_names_failed->insert(cluster_name);
2713
+ continue;
1734
2714
  }
1735
- if (envoy_config_cluster_v3_Cluster_type(cluster) !=
2715
+ if (envoy_config_cluster_v3_Cluster_type(cluster) ==
1736
2716
  envoy_config_cluster_v3_Cluster_EDS) {
1737
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType is not EDS.");
1738
- }
1739
- // Check the EDS config source.
1740
- const envoy_config_cluster_v3_Cluster_EdsClusterConfig* eds_cluster_config =
1741
- envoy_config_cluster_v3_Cluster_eds_cluster_config(cluster);
1742
- const envoy_config_core_v3_ConfigSource* eds_config =
1743
- envoy_config_cluster_v3_Cluster_EdsClusterConfig_eds_config(
1744
- eds_cluster_config);
1745
- if (!envoy_config_core_v3_ConfigSource_has_ads(eds_config)) {
1746
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1747
- "EDS ConfigSource is not ADS.");
1748
- }
1749
- // Record EDS service_name (if any).
1750
- upb_strview service_name =
1751
- envoy_config_cluster_v3_Cluster_EdsClusterConfig_service_name(
1752
- eds_cluster_config);
1753
- if (service_name.size != 0) {
1754
- cds_update.eds_service_name = UpbStringToStdString(service_name);
2717
+ cds_update.cluster_type = XdsApi::CdsUpdate::ClusterType::EDS;
2718
+ // Check the EDS config source.
2719
+ const envoy_config_cluster_v3_Cluster_EdsClusterConfig*
2720
+ eds_cluster_config =
2721
+ envoy_config_cluster_v3_Cluster_eds_cluster_config(cluster);
2722
+ const envoy_config_core_v3_ConfigSource* eds_config =
2723
+ envoy_config_cluster_v3_Cluster_EdsClusterConfig_eds_config(
2724
+ eds_cluster_config);
2725
+ if (!envoy_config_core_v3_ConfigSource_has_ads(eds_config)) {
2726
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2727
+ absl::StrCat(cluster_name, ": EDS ConfigSource is not ADS.")
2728
+ .c_str()));
2729
+ resource_names_failed->insert(cluster_name);
2730
+ continue;
2731
+ }
2732
+ // Record EDS service_name (if any).
2733
+ upb_strview service_name =
2734
+ envoy_config_cluster_v3_Cluster_EdsClusterConfig_service_name(
2735
+ eds_cluster_config);
2736
+ if (service_name.size != 0) {
2737
+ cds_update.eds_service_name = UpbStringToStdString(service_name);
2738
+ }
2739
+ } else if (!XdsAggregateAndLogicalDnsClusterEnabled()) {
2740
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2741
+ absl::StrCat(cluster_name, ": DiscoveryType is not valid.").c_str()));
2742
+ resource_names_failed->insert(cluster_name);
2743
+ continue;
2744
+ } else if (envoy_config_cluster_v3_Cluster_type(cluster) ==
2745
+ envoy_config_cluster_v3_Cluster_LOGICAL_DNS) {
2746
+ cds_update.cluster_type = XdsApi::CdsUpdate::ClusterType::LOGICAL_DNS;
2747
+ } else {
2748
+ if (envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) {
2749
+ const envoy_config_cluster_v3_Cluster_CustomClusterType*
2750
+ custom_cluster_type =
2751
+ envoy_config_cluster_v3_Cluster_cluster_type(cluster);
2752
+ upb_strview type_name =
2753
+ envoy_config_cluster_v3_Cluster_CustomClusterType_name(
2754
+ custom_cluster_type);
2755
+ if (UpbStringToAbsl(type_name) == "envoy.clusters.aggregate") {
2756
+ cds_update.cluster_type = XdsApi::CdsUpdate::ClusterType::AGGREGATE;
2757
+ // Retrieve aggregate clusters.
2758
+ const google_protobuf_Any* typed_config =
2759
+ envoy_config_cluster_v3_Cluster_CustomClusterType_typed_config(
2760
+ custom_cluster_type);
2761
+ const upb_strview aggregate_cluster_config_upb_strview =
2762
+ google_protobuf_Any_value(typed_config);
2763
+ const envoy_extensions_clusters_aggregate_v3_ClusterConfig*
2764
+ aggregate_cluster_config =
2765
+ envoy_extensions_clusters_aggregate_v3_ClusterConfig_parse(
2766
+ aggregate_cluster_config_upb_strview.data,
2767
+ aggregate_cluster_config_upb_strview.size, context.arena);
2768
+ if (aggregate_cluster_config == nullptr) {
2769
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2770
+ absl::StrCat(cluster_name, ": Can't parse aggregate cluster.")
2771
+ .c_str()));
2772
+ resource_names_failed->insert(cluster_name);
2773
+ continue;
2774
+ }
2775
+ size_t size;
2776
+ const upb_strview* clusters =
2777
+ envoy_extensions_clusters_aggregate_v3_ClusterConfig_clusters(
2778
+ aggregate_cluster_config, &size);
2779
+ for (size_t i = 0; i < size; ++i) {
2780
+ const upb_strview cluster = clusters[i];
2781
+ cds_update.prioritized_cluster_names.emplace_back(
2782
+ UpbStringToStdString(cluster));
2783
+ }
2784
+ } else {
2785
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2786
+ absl::StrCat(cluster_name, ": DiscoveryType is not valid.")
2787
+ .c_str()));
2788
+ resource_names_failed->insert(cluster_name);
2789
+ continue;
2790
+ }
2791
+ } else {
2792
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2793
+ absl::StrCat(cluster_name, ": DiscoveryType is not valid.")
2794
+ .c_str()));
2795
+ resource_names_failed->insert(cluster_name);
2796
+ continue;
2797
+ }
1755
2798
  }
1756
2799
  // Check the LB policy.
1757
- if (envoy_config_cluster_v3_Cluster_lb_policy(cluster) !=
2800
+ if (envoy_config_cluster_v3_Cluster_lb_policy(cluster) ==
1758
2801
  envoy_config_cluster_v3_Cluster_ROUND_ROBIN) {
1759
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1760
- "LB policy is not ROUND_ROBIN.");
2802
+ cds_update.lb_policy = "ROUND_ROBIN";
2803
+ } else if (XdsRingHashEnabled() &&
2804
+ envoy_config_cluster_v3_Cluster_lb_policy(cluster) ==
2805
+ envoy_config_cluster_v3_Cluster_RING_HASH) {
2806
+ cds_update.lb_policy = "RING_HASH";
2807
+ // Record ring hash lb config
2808
+ auto* ring_hash_config =
2809
+ envoy_config_cluster_v3_Cluster_ring_hash_lb_config(cluster);
2810
+ if (ring_hash_config == nullptr) {
2811
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2812
+ absl::StrCat(cluster_name,
2813
+ ": ring hash lb config required but not present.")
2814
+ .c_str()));
2815
+ resource_names_failed->insert(cluster_name);
2816
+ continue;
2817
+ }
2818
+ const google_protobuf_UInt64Value* max_ring_size =
2819
+ envoy_config_cluster_v3_Cluster_RingHashLbConfig_maximum_ring_size(
2820
+ ring_hash_config);
2821
+ if (max_ring_size != nullptr) {
2822
+ cds_update.max_ring_size =
2823
+ google_protobuf_UInt64Value_value(max_ring_size);
2824
+ if (cds_update.max_ring_size > 8388608 ||
2825
+ cds_update.max_ring_size == 0) {
2826
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2827
+ absl::StrCat(
2828
+ cluster_name,
2829
+ ": max_ring_size is not in the range of 1 to 8388608.")
2830
+ .c_str()));
2831
+ resource_names_failed->insert(cluster_name);
2832
+ continue;
2833
+ }
2834
+ }
2835
+ const google_protobuf_UInt64Value* min_ring_size =
2836
+ envoy_config_cluster_v3_Cluster_RingHashLbConfig_minimum_ring_size(
2837
+ ring_hash_config);
2838
+ if (min_ring_size != nullptr) {
2839
+ cds_update.min_ring_size =
2840
+ google_protobuf_UInt64Value_value(min_ring_size);
2841
+ if (cds_update.min_ring_size > 8388608 ||
2842
+ cds_update.min_ring_size == 0) {
2843
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2844
+ absl::StrCat(
2845
+ cluster_name,
2846
+ ": min_ring_size is not in the range of 1 to 8388608.")
2847
+ .c_str()));
2848
+ resource_names_failed->insert(cluster_name);
2849
+ continue;
2850
+ }
2851
+ if (cds_update.min_ring_size > cds_update.max_ring_size) {
2852
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2853
+ absl::StrCat(
2854
+ cluster_name,
2855
+ ": min_ring_size cannot be greater than max_ring_size.")
2856
+ .c_str()));
2857
+ resource_names_failed->insert(cluster_name);
2858
+ continue;
2859
+ }
2860
+ }
2861
+ if (envoy_config_cluster_v3_Cluster_RingHashLbConfig_hash_function(
2862
+ ring_hash_config) ==
2863
+ envoy_config_cluster_v3_Cluster_RingHashLbConfig_XX_HASH) {
2864
+ cds_update.hash_function = XdsApi::CdsUpdate::HashFunction::XX_HASH;
2865
+ } else if (
2866
+ envoy_config_cluster_v3_Cluster_RingHashLbConfig_hash_function(
2867
+ ring_hash_config) ==
2868
+ envoy_config_cluster_v3_Cluster_RingHashLbConfig_MURMUR_HASH_2) {
2869
+ cds_update.hash_function =
2870
+ XdsApi::CdsUpdate::HashFunction::MURMUR_HASH_2;
2871
+ } else {
2872
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2873
+ absl::StrCat(cluster_name,
2874
+ ": ring hash lb config has invalid hash function.")
2875
+ .c_str()));
2876
+ resource_names_failed->insert(cluster_name);
2877
+ continue;
2878
+ }
2879
+ } else {
2880
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2881
+ absl::StrCat(cluster_name, ": LB policy is not supported.").c_str()));
2882
+ resource_names_failed->insert(cluster_name);
2883
+ continue;
1761
2884
  }
1762
2885
  if (XdsSecurityEnabled()) {
1763
2886
  // Record Upstream tls context
@@ -1776,10 +2899,14 @@ grpc_error* CdsResponseParse(
1776
2899
  auto* upstream_tls_context =
1777
2900
  envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_parse(
1778
2901
  encoded_upstream_tls_context.data,
1779
- encoded_upstream_tls_context.size, arena);
2902
+ encoded_upstream_tls_context.size, context.arena);
1780
2903
  if (upstream_tls_context == nullptr) {
1781
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1782
- "Can't decode upstream tls context.");
2904
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2905
+ absl::StrCat(cluster_name,
2906
+ ": Can't decode upstream tls context.")
2907
+ .c_str()));
2908
+ resource_names_failed->insert(cluster_name);
2909
+ continue;
1783
2910
  }
1784
2911
  auto* common_tls_context =
1785
2912
  envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_common_tls_context(
@@ -1787,15 +2914,28 @@ grpc_error* CdsResponseParse(
1787
2914
  if (common_tls_context != nullptr) {
1788
2915
  grpc_error* error = CommonTlsContextParse(
1789
2916
  common_tls_context, &cds_update.common_tls_context);
1790
- if (error != GRPC_ERROR_NONE) return error;
2917
+ if (error != GRPC_ERROR_NONE) {
2918
+ errors.push_back(grpc_error_add_child(
2919
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2920
+ absl::StrCat(cluster_name, ": error in TLS context")
2921
+ .c_str()),
2922
+ error));
2923
+ resource_names_failed->insert(cluster_name);
2924
+ continue;
2925
+ }
1791
2926
  }
1792
2927
  }
1793
2928
  if (cds_update.common_tls_context.combined_validation_context
1794
2929
  .validation_context_certificate_provider_instance
1795
2930
  .instance_name.empty()) {
1796
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1797
- "TLS configuration provided but no "
1798
- "validation_context_certificate_provider_instance found.");
2931
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2932
+ absl::StrCat(cluster_name,
2933
+ "TLS configuration provided but no "
2934
+ "validation_context_certificate_provider_instance "
2935
+ "found.")
2936
+ .c_str()));
2937
+ resource_names_failed->insert(cluster_name);
2938
+ continue;
1799
2939
  }
1800
2940
  }
1801
2941
  }
@@ -1805,8 +2945,11 @@ grpc_error* CdsResponseParse(
1805
2945
  envoy_config_cluster_v3_Cluster_lrs_server(cluster);
1806
2946
  if (lrs_server != nullptr) {
1807
2947
  if (!envoy_config_core_v3_ConfigSource_has_self(lrs_server)) {
1808
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1809
- "LRS ConfigSource is not self.");
2948
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
2949
+ absl::StrCat(cluster_name, ": LRS ConfigSource is not self.")
2950
+ .c_str()));
2951
+ resource_names_failed->insert(cluster_name);
2952
+ continue;
1810
2953
  }
1811
2954
  cds_update.lrs_load_reporting_server_name.emplace("");
1812
2955
  }
@@ -1837,7 +2980,7 @@ grpc_error* CdsResponseParse(
1837
2980
  }
1838
2981
  }
1839
2982
  }
1840
- return GRPC_ERROR_NONE;
2983
+ return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing CDS response", &errors);
1841
2984
  }
1842
2985
 
1843
2986
  grpc_error* ServerAddressParseAndAppend(
@@ -1865,7 +3008,9 @@ grpc_error* ServerAddressParseAndAppend(
1865
3008
  }
1866
3009
  // Populate grpc_resolved_address.
1867
3010
  grpc_resolved_address addr;
1868
- grpc_string_to_sockaddr(&addr, address_str.c_str(), port);
3011
+ grpc_error* error =
3012
+ grpc_string_to_sockaddr_new(&addr, address_str.c_str(), port);
3013
+ if (error != GRPC_ERROR_NONE) return error;
1869
3014
  // Append the address to the list.
1870
3015
  list->emplace_back(addr, nullptr);
1871
3016
  return GRPC_ERROR_NONE;
@@ -1888,6 +3033,9 @@ grpc_error* LocalityParse(
1888
3033
  const envoy_config_core_v3_Locality* locality =
1889
3034
  envoy_config_endpoint_v3_LocalityLbEndpoints_locality(
1890
3035
  locality_lb_endpoints);
3036
+ if (locality == nullptr) {
3037
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty locality.");
3038
+ }
1891
3039
  std::string region =
1892
3040
  UpbStringToStdString(envoy_config_core_v3_Locality_region(locality));
1893
3041
  std::string zone =
@@ -1952,10 +3100,12 @@ grpc_error* DropParseAndAppend(
1952
3100
  }
1953
3101
 
1954
3102
  grpc_error* EdsResponseParse(
1955
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
3103
+ const EncodingContext& context,
1956
3104
  const envoy_service_discovery_v3_DiscoveryResponse* response,
1957
3105
  const std::set<absl::string_view>& expected_eds_service_names,
1958
- XdsApi::EdsUpdateMap* eds_update_map, upb_arena* arena) {
3106
+ XdsApi::EdsUpdateMap* eds_update_map,
3107
+ std::set<std::string>* resource_names_failed) {
3108
+ std::vector<grpc_error*> errors;
1959
3109
  // Get the resources from the response.
1960
3110
  size_t size;
1961
3111
  const google_protobuf_Any* const* resources =
@@ -1965,7 +3115,10 @@ grpc_error* EdsResponseParse(
1965
3115
  absl::string_view type_url =
1966
3116
  UpbStringToAbsl(google_protobuf_Any_type_url(resources[i]));
1967
3117
  if (!IsEds(type_url)) {
1968
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not EDS.");
3118
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
3119
+ absl::StrCat("resource index ", i, ": Resource is not EDS.")
3120
+ .c_str()));
3121
+ continue;
1969
3122
  }
1970
3123
  // Get the cluster_load_assignment.
1971
3124
  upb_strview encoded_cluster_load_assignment =
@@ -1973,13 +3126,15 @@ grpc_error* EdsResponseParse(
1973
3126
  envoy_config_endpoint_v3_ClusterLoadAssignment* cluster_load_assignment =
1974
3127
  envoy_config_endpoint_v3_ClusterLoadAssignment_parse(
1975
3128
  encoded_cluster_load_assignment.data,
1976
- encoded_cluster_load_assignment.size, arena);
3129
+ encoded_cluster_load_assignment.size, context.arena);
1977
3130
  if (cluster_load_assignment == nullptr) {
1978
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1979
- "Can't parse cluster_load_assignment.");
3131
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
3132
+ absl::StrCat("resource index ", i,
3133
+ ": Can't parse cluster_load_assignment.")
3134
+ .c_str()));
3135
+ continue;
1980
3136
  }
1981
- MaybeLogClusterLoadAssignment(client, tracer, symtab,
1982
- cluster_load_assignment);
3137
+ MaybeLogClusterLoadAssignment(context, cluster_load_assignment);
1983
3138
  // Check the EDS service name. Ignore unexpected names.
1984
3139
  std::string eds_service_name = UpbStringToStdString(
1985
3140
  envoy_config_endpoint_v3_ClusterLoadAssignment_cluster_name(
@@ -1990,22 +3145,29 @@ grpc_error* EdsResponseParse(
1990
3145
  }
1991
3146
  // Fail on duplicate resources.
1992
3147
  if (eds_update_map->find(eds_service_name) != eds_update_map->end()) {
1993
- return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
3148
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
1994
3149
  absl::StrCat("duplicate resource name \"", eds_service_name, "\"")
1995
- .c_str());
3150
+ .c_str()));
3151
+ resource_names_failed->insert(eds_service_name);
3152
+ continue;
1996
3153
  }
1997
- XdsApi::EdsUpdate& eds_update =
1998
- (*eds_update_map)[std::move(eds_service_name)];
3154
+ // Serialize into JSON and store it in the EdsUpdateMap
3155
+ XdsApi::EdsResourceData& eds_resource_data =
3156
+ (*eds_update_map)[eds_service_name];
3157
+ XdsApi::EdsUpdate& eds_update = eds_resource_data.resource;
3158
+ eds_resource_data.serialized_proto =
3159
+ UpbStringToStdString(encoded_cluster_load_assignment);
1999
3160
  // Get the endpoints.
2000
3161
  size_t locality_size;
2001
3162
  const envoy_config_endpoint_v3_LocalityLbEndpoints* const* endpoints =
2002
3163
  envoy_config_endpoint_v3_ClusterLoadAssignment_endpoints(
2003
3164
  cluster_load_assignment, &locality_size);
3165
+ grpc_error* error = GRPC_ERROR_NONE;
2004
3166
  for (size_t j = 0; j < locality_size; ++j) {
2005
3167
  size_t priority;
2006
3168
  XdsApi::EdsUpdate::Priority::Locality locality;
2007
- grpc_error* error = LocalityParse(endpoints[j], &locality, &priority);
2008
- if (error != GRPC_ERROR_NONE) return error;
3169
+ error = LocalityParse(endpoints[j], &locality, &priority);
3170
+ if (error != GRPC_ERROR_NONE) break;
2009
3171
  // Filter out locality with weight 0.
2010
3172
  if (locality.lb_weight == 0) continue;
2011
3173
  // Make sure prorities is big enough. Note that they might not
@@ -2016,10 +3178,21 @@ grpc_error* EdsResponseParse(
2016
3178
  eds_update.priorities[priority].localities.emplace(locality.name.get(),
2017
3179
  std::move(locality));
2018
3180
  }
3181
+ if (error != GRPC_ERROR_NONE) {
3182
+ errors.push_back(grpc_error_add_child(
3183
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(
3184
+ absl::StrCat(eds_service_name, ": locality validation error")
3185
+ .c_str()),
3186
+ error));
3187
+ resource_names_failed->insert(eds_service_name);
3188
+ continue;
3189
+ }
2019
3190
  for (const auto& priority : eds_update.priorities) {
2020
3191
  if (priority.localities.empty()) {
2021
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2022
- "EDS update includes sparse priority list");
3192
+ errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
3193
+ absl::StrCat(eds_service_name, ": sparse priority list").c_str()));
3194
+ resource_names_failed->insert(eds_service_name);
3195
+ continue;
2023
3196
  }
2024
3197
  }
2025
3198
  // Get the drop config.
@@ -2034,13 +3207,22 @@ grpc_error* EdsResponseParse(
2034
3207
  envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_drop_overloads(
2035
3208
  policy, &drop_size);
2036
3209
  for (size_t j = 0; j < drop_size; ++j) {
2037
- grpc_error* error =
3210
+ error =
2038
3211
  DropParseAndAppend(drop_overload[j], eds_update.drop_config.get());
2039
- if (error != GRPC_ERROR_NONE) return error;
3212
+ if (error != GRPC_ERROR_NONE) break;
3213
+ }
3214
+ if (error != GRPC_ERROR_NONE) {
3215
+ errors.push_back(grpc_error_add_child(
3216
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(
3217
+ absl::StrCat(eds_service_name, ": drop config validation error")
3218
+ .c_str()),
3219
+ error));
3220
+ resource_names_failed->insert(eds_service_name);
3221
+ continue;
2040
3222
  }
2041
3223
  }
2042
3224
  }
2043
- return GRPC_ERROR_NONE;
3225
+ return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing EDS response", &errors);
2044
3226
  }
2045
3227
 
2046
3228
  std::string TypeUrlInternalToExternal(absl::string_view type_url) {
@@ -2056,16 +3238,27 @@ std::string TypeUrlInternalToExternal(absl::string_view type_url) {
2056
3238
  return std::string(type_url);
2057
3239
  }
2058
3240
 
3241
+ template <typename UpdateMap>
3242
+ void MoveUpdatesToFailedSet(UpdateMap* update_map,
3243
+ std::set<std::string>* resource_names_failed) {
3244
+ for (const auto& p : *update_map) {
3245
+ resource_names_failed->insert(p.first);
3246
+ }
3247
+ update_map->clear();
3248
+ }
3249
+
2059
3250
  } // namespace
2060
3251
 
2061
3252
  XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
2062
- const grpc_slice& encoded_response,
3253
+ const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response,
2063
3254
  const std::set<absl::string_view>& expected_listener_names,
2064
3255
  const std::set<absl::string_view>& expected_route_configuration_names,
2065
3256
  const std::set<absl::string_view>& expected_cluster_names,
2066
3257
  const std::set<absl::string_view>& expected_eds_service_names) {
2067
3258
  AdsParseResult result;
2068
3259
  upb::Arena arena;
3260
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
3261
+ server.ShouldUseV3()};
2069
3262
  // Decode the response.
2070
3263
  const envoy_service_discovery_v3_DiscoveryResponse* response =
2071
3264
  envoy_service_discovery_v3_DiscoveryResponse_parse(
@@ -2077,7 +3270,7 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
2077
3270
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode DiscoveryResponse.");
2078
3271
  return result;
2079
3272
  }
2080
- MaybeLogDiscoveryResponse(client_, tracer_, symtab_.ptr(), response);
3273
+ MaybeLogDiscoveryResponse(context, response);
2081
3274
  // Record the type_url, the version_info, and the nonce of the response.
2082
3275
  result.type_url = TypeUrlInternalToExternal(UpbStringToAbsl(
2083
3276
  envoy_service_discovery_v3_DiscoveryResponse_type_url(response)));
@@ -2087,22 +3280,37 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
2087
3280
  envoy_service_discovery_v3_DiscoveryResponse_nonce(response));
2088
3281
  // Parse the response according to the resource type.
2089
3282
  if (IsLds(result.type_url)) {
2090
- result.parse_error = LdsResponseParse(client_, tracer_, symtab_.ptr(),
2091
- response, expected_listener_names,
2092
- &result.lds_update_map, arena.ptr());
3283
+ result.parse_error =
3284
+ LdsResponseParse(context, response, expected_listener_names,
3285
+ &result.lds_update_map, &result.resource_names_failed);
3286
+ if (result.parse_error != GRPC_ERROR_NONE) {
3287
+ MoveUpdatesToFailedSet(&result.lds_update_map,
3288
+ &result.resource_names_failed);
3289
+ }
2093
3290
  } else if (IsRds(result.type_url)) {
2094
3291
  result.parse_error =
2095
- RdsResponseParse(client_, tracer_, symtab_.ptr(), response,
2096
- expected_route_configuration_names,
2097
- &result.rds_update_map, arena.ptr());
3292
+ RdsResponseParse(context, response, expected_route_configuration_names,
3293
+ &result.rds_update_map, &result.resource_names_failed);
3294
+ if (result.parse_error != GRPC_ERROR_NONE) {
3295
+ MoveUpdatesToFailedSet(&result.rds_update_map,
3296
+ &result.resource_names_failed);
3297
+ }
2098
3298
  } else if (IsCds(result.type_url)) {
2099
- result.parse_error = CdsResponseParse(client_, tracer_, symtab_.ptr(),
2100
- response, expected_cluster_names,
2101
- &result.cds_update_map, arena.ptr());
3299
+ result.parse_error =
3300
+ CdsResponseParse(context, response, expected_cluster_names,
3301
+ &result.cds_update_map, &result.resource_names_failed);
3302
+ if (result.parse_error != GRPC_ERROR_NONE) {
3303
+ MoveUpdatesToFailedSet(&result.cds_update_map,
3304
+ &result.resource_names_failed);
3305
+ }
2102
3306
  } else if (IsEds(result.type_url)) {
2103
- result.parse_error = EdsResponseParse(client_, tracer_, symtab_.ptr(),
2104
- response, expected_eds_service_names,
2105
- &result.eds_update_map, arena.ptr());
3307
+ result.parse_error =
3308
+ EdsResponseParse(context, response, expected_eds_service_names,
3309
+ &result.eds_update_map, &result.resource_names_failed);
3310
+ if (result.parse_error != GRPC_ERROR_NONE) {
3311
+ MoveUpdatesToFailedSet(&result.eds_update_map,
3312
+ &result.resource_names_failed);
3313
+ }
2106
3314
  }
2107
3315
  return result;
2108
3316
  }
@@ -2110,25 +3318,25 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
2110
3318
  namespace {
2111
3319
 
2112
3320
  void MaybeLogLrsRequest(
2113
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
3321
+ const EncodingContext& context,
2114
3322
  const envoy_service_load_stats_v3_LoadStatsRequest* request) {
2115
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
3323
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
2116
3324
  gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
2117
3325
  const upb_msgdef* msg_type =
2118
- envoy_service_load_stats_v3_LoadStatsRequest_getmsgdef(symtab);
3326
+ envoy_service_load_stats_v3_LoadStatsRequest_getmsgdef(context.symtab);
2119
3327
  char buf[10240];
2120
3328
  upb_text_encode(request, msg_type, nullptr, 0, buf, sizeof(buf));
2121
- gpr_log(GPR_DEBUG, "[xds_client %p] constructed LRS request: %s", client,
2122
- buf);
3329
+ gpr_log(GPR_DEBUG, "[xds_client %p] constructed LRS request: %s",
3330
+ context.client, buf);
2123
3331
  }
2124
3332
  }
2125
3333
 
2126
3334
  grpc_slice SerializeLrsRequest(
2127
- const envoy_service_load_stats_v3_LoadStatsRequest* request,
2128
- upb_arena* arena) {
3335
+ const EncodingContext& context,
3336
+ const envoy_service_load_stats_v3_LoadStatsRequest* request) {
2129
3337
  size_t output_length;
2130
3338
  char* output = envoy_service_load_stats_v3_LoadStatsRequest_serialize(
2131
- request, arena, &output_length);
3339
+ request, context.arena, &output_length);
2132
3340
  return grpc_slice_from_copied_buffer(output, output_length);
2133
3341
  }
2134
3342
 
@@ -2137,6 +3345,8 @@ grpc_slice SerializeLrsRequest(
2137
3345
  grpc_slice XdsApi::CreateLrsInitialRequest(
2138
3346
  const XdsBootstrap::XdsServer& server) {
2139
3347
  upb::Arena arena;
3348
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
3349
+ server.ShouldUseV3()};
2140
3350
  // Create a request.
2141
3351
  envoy_service_load_stats_v3_LoadStatsRequest* request =
2142
3352
  envoy_service_load_stats_v3_LoadStatsRequest_new(arena.ptr());
@@ -2144,25 +3354,25 @@ grpc_slice XdsApi::CreateLrsInitialRequest(
2144
3354
  envoy_config_core_v3_Node* node_msg =
2145
3355
  envoy_service_load_stats_v3_LoadStatsRequest_mutable_node(request,
2146
3356
  arena.ptr());
2147
- PopulateNode(arena.ptr(), node_, server.ShouldUseV3(), build_version_,
2148
- user_agent_name_, node_msg);
3357
+ PopulateNode(context, node_, build_version_, user_agent_name_, node_msg);
2149
3358
  envoy_config_core_v3_Node_add_client_features(
2150
3359
  node_msg, upb_strview_makez("envoy.lrs.supports_send_all_clusters"),
2151
3360
  arena.ptr());
2152
- MaybeLogLrsRequest(client_, tracer_, symtab_.ptr(), request);
2153
- return SerializeLrsRequest(request, arena.ptr());
3361
+ MaybeLogLrsRequest(context, request);
3362
+ return SerializeLrsRequest(context, request);
2154
3363
  }
2155
3364
 
2156
3365
  namespace {
2157
3366
 
2158
3367
  void LocalityStatsPopulate(
3368
+ const EncodingContext& context,
2159
3369
  envoy_config_endpoint_v3_UpstreamLocalityStats* output,
2160
3370
  const XdsLocalityName& locality_name,
2161
- const XdsClusterLocalityStats::Snapshot& snapshot, upb_arena* arena) {
3371
+ const XdsClusterLocalityStats::Snapshot& snapshot) {
2162
3372
  // Set locality.
2163
3373
  envoy_config_core_v3_Locality* locality =
2164
- envoy_config_endpoint_v3_UpstreamLocalityStats_mutable_locality(output,
2165
- arena);
3374
+ envoy_config_endpoint_v3_UpstreamLocalityStats_mutable_locality(
3375
+ output, context.arena);
2166
3376
  if (!locality_name.region().empty()) {
2167
3377
  envoy_config_core_v3_Locality_set_region(
2168
3378
  locality, StdStringToUpbString(locality_name.region()));
@@ -2190,7 +3400,7 @@ void LocalityStatsPopulate(
2190
3400
  const XdsClusterLocalityStats::BackendMetric& metric_value = p.second;
2191
3401
  envoy_config_endpoint_v3_EndpointLoadMetricStats* load_metric =
2192
3402
  envoy_config_endpoint_v3_UpstreamLocalityStats_add_load_metric_stats(
2193
- output, arena);
3403
+ output, context.arena);
2194
3404
  envoy_config_endpoint_v3_EndpointLoadMetricStats_set_metric_name(
2195
3405
  load_metric, StdStringToUpbString(metric_name));
2196
3406
  envoy_config_endpoint_v3_EndpointLoadMetricStats_set_num_requests_finished_with_metric(
@@ -2205,6 +3415,8 @@ void LocalityStatsPopulate(
2205
3415
  grpc_slice XdsApi::CreateLrsRequest(
2206
3416
  ClusterLoadReportMap cluster_load_report_map) {
2207
3417
  upb::Arena arena;
3418
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
3419
+ false};
2208
3420
  // Create a request.
2209
3421
  envoy_service_load_stats_v3_LoadStatsRequest* request =
2210
3422
  envoy_service_load_stats_v3_LoadStatsRequest_new(arena.ptr());
@@ -2231,8 +3443,7 @@ grpc_slice XdsApi::CreateLrsRequest(
2231
3443
  envoy_config_endpoint_v3_UpstreamLocalityStats* locality_stats =
2232
3444
  envoy_config_endpoint_v3_ClusterStats_add_upstream_locality_stats(
2233
3445
  cluster_stats, arena.ptr());
2234
- LocalityStatsPopulate(locality_stats, locality_name, snapshot,
2235
- arena.ptr());
3446
+ LocalityStatsPopulate(context, locality_stats, locality_name, snapshot);
2236
3447
  }
2237
3448
  // Add dropped requests.
2238
3449
  uint64_t total_dropped_requests = 0;
@@ -2261,8 +3472,8 @@ grpc_slice XdsApi::CreateLrsRequest(
2261
3472
  google_protobuf_Duration_set_seconds(load_report_interval, timespec.tv_sec);
2262
3473
  google_protobuf_Duration_set_nanos(load_report_interval, timespec.tv_nsec);
2263
3474
  }
2264
- MaybeLogLrsRequest(client_, tracer_, symtab_.ptr(), request);
2265
- return SerializeLrsRequest(request, arena.ptr());
3475
+ MaybeLogLrsRequest(context, request);
3476
+ return SerializeLrsRequest(context, request);
2266
3477
  }
2267
3478
 
2268
3479
  grpc_error* XdsApi::ParseLrsResponse(const grpc_slice& encoded_response,
@@ -2305,4 +3516,276 @@ grpc_error* XdsApi::ParseLrsResponse(const grpc_slice& encoded_response,
2305
3516
  return GRPC_ERROR_NONE;
2306
3517
  }
2307
3518
 
3519
+ namespace {
3520
+ google_protobuf_Timestamp* GrpcMillisToTimestamp(const EncodingContext& context,
3521
+ grpc_millis value) {
3522
+ google_protobuf_Timestamp* timestamp =
3523
+ google_protobuf_Timestamp_new(context.arena);
3524
+ gpr_timespec timespec = grpc_millis_to_timespec(value, GPR_CLOCK_REALTIME);
3525
+ google_protobuf_Timestamp_set_seconds(timestamp, timespec.tv_sec);
3526
+ google_protobuf_Timestamp_set_nanos(timestamp, timespec.tv_nsec);
3527
+ return timestamp;
3528
+ }
3529
+
3530
+ envoy_admin_v3_UpdateFailureState* CreateUpdateFailureStateUpb(
3531
+ const EncodingContext& context,
3532
+ const XdsApi::ResourceMetadata* resource_metadata) {
3533
+ auto* update_failure_state =
3534
+ envoy_admin_v3_UpdateFailureState_new(context.arena);
3535
+ envoy_admin_v3_UpdateFailureState_set_details(
3536
+ update_failure_state,
3537
+ StdStringToUpbString(resource_metadata->failed_details));
3538
+ envoy_admin_v3_UpdateFailureState_set_version_info(
3539
+ update_failure_state,
3540
+ StdStringToUpbString(resource_metadata->failed_version));
3541
+ envoy_admin_v3_UpdateFailureState_set_last_update_attempt(
3542
+ update_failure_state,
3543
+ GrpcMillisToTimestamp(context, resource_metadata->failed_update_time));
3544
+ return update_failure_state;
3545
+ }
3546
+
3547
+ void DumpLdsConfig(const EncodingContext& context,
3548
+ const XdsApi::ResourceTypeMetadata& resource_type_metadata,
3549
+ envoy_service_status_v3_PerXdsConfig* per_xds_config) {
3550
+ upb_strview kLdsTypeUrlUpb = upb_strview_makez(XdsApi::kLdsTypeUrl);
3551
+ auto* listener_config_dump =
3552
+ envoy_service_status_v3_PerXdsConfig_mutable_listener_config(
3553
+ per_xds_config, context.arena);
3554
+ envoy_admin_v3_ListenersConfigDump_set_version_info(
3555
+ listener_config_dump,
3556
+ StdStringToUpbString(resource_type_metadata.version));
3557
+ for (auto& p : resource_type_metadata.resource_metadata_map) {
3558
+ absl::string_view name = p.first;
3559
+ const XdsApi::ResourceMetadata* meta = p.second;
3560
+ const upb_strview name_upb = StdStringToUpbString(name);
3561
+ auto* dynamic_listener =
3562
+ envoy_admin_v3_ListenersConfigDump_add_dynamic_listeners(
3563
+ listener_config_dump, context.arena);
3564
+ envoy_admin_v3_ListenersConfigDump_DynamicListener_set_name(
3565
+ dynamic_listener, name_upb);
3566
+ envoy_admin_v3_ListenersConfigDump_DynamicListener_set_client_status(
3567
+ dynamic_listener, meta->client_status);
3568
+ if (!meta->serialized_proto.empty()) {
3569
+ // Set in-effective listeners
3570
+ auto* dynamic_listener_state =
3571
+ envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_active_state(
3572
+ dynamic_listener, context.arena);
3573
+ envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_version_info(
3574
+ dynamic_listener_state, StdStringToUpbString(meta->version));
3575
+ envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_last_updated(
3576
+ dynamic_listener_state,
3577
+ GrpcMillisToTimestamp(context, meta->update_time));
3578
+ auto* listener_any =
3579
+ envoy_admin_v3_ListenersConfigDump_DynamicListenerState_mutable_listener(
3580
+ dynamic_listener_state, context.arena);
3581
+ google_protobuf_Any_set_type_url(listener_any, kLdsTypeUrlUpb);
3582
+ google_protobuf_Any_set_value(
3583
+ listener_any, StdStringToUpbString(meta->serialized_proto));
3584
+ }
3585
+ if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
3586
+ // Set error_state if NACKED
3587
+ envoy_admin_v3_ListenersConfigDump_DynamicListener_set_error_state(
3588
+ dynamic_listener, CreateUpdateFailureStateUpb(context, meta));
3589
+ }
3590
+ }
3591
+ }
3592
+
3593
+ void DumpRdsConfig(const EncodingContext& context,
3594
+ const XdsApi::ResourceTypeMetadata& resource_type_metadata,
3595
+ envoy_service_status_v3_PerXdsConfig* per_xds_config) {
3596
+ upb_strview kRdsTypeUrlUpb = upb_strview_makez(XdsApi::kRdsTypeUrl);
3597
+ auto* route_config_dump =
3598
+ envoy_service_status_v3_PerXdsConfig_mutable_route_config(per_xds_config,
3599
+ context.arena);
3600
+ for (auto& p : resource_type_metadata.resource_metadata_map) {
3601
+ absl::string_view name = p.first;
3602
+ const XdsApi::ResourceMetadata* meta = p.second;
3603
+ const upb_strview name_upb = StdStringToUpbString(name);
3604
+ auto* dynamic_route_config =
3605
+ envoy_admin_v3_RoutesConfigDump_add_dynamic_route_configs(
3606
+ route_config_dump, context.arena);
3607
+ envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_client_status(
3608
+ dynamic_route_config, meta->client_status);
3609
+ auto* route_config_any =
3610
+ envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_mutable_route_config(
3611
+ dynamic_route_config, context.arena);
3612
+ if (!meta->serialized_proto.empty()) {
3613
+ // Set in-effective route configs
3614
+ envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_version_info(
3615
+ dynamic_route_config, StdStringToUpbString(meta->version));
3616
+ envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_last_updated(
3617
+ dynamic_route_config,
3618
+ GrpcMillisToTimestamp(context, meta->update_time));
3619
+ google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb);
3620
+ google_protobuf_Any_set_value(
3621
+ route_config_any, StdStringToUpbString(meta->serialized_proto));
3622
+ } else {
3623
+ // If there isn't a working route config, we still need to print the
3624
+ // name.
3625
+ auto* route_config =
3626
+ envoy_config_route_v3_RouteConfiguration_new(context.arena);
3627
+ envoy_config_route_v3_RouteConfiguration_set_name(route_config, name_upb);
3628
+ size_t length;
3629
+ char* bytes = envoy_config_route_v3_RouteConfiguration_serialize(
3630
+ route_config, context.arena, &length);
3631
+ google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb);
3632
+ google_protobuf_Any_set_value(route_config_any,
3633
+ upb_strview_make(bytes, length));
3634
+ }
3635
+ if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
3636
+ // Set error_state if NACKED
3637
+ envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_error_state(
3638
+ dynamic_route_config, CreateUpdateFailureStateUpb(context, meta));
3639
+ }
3640
+ }
3641
+ }
3642
+
3643
+ void DumpCdsConfig(const EncodingContext& context,
3644
+ const XdsApi::ResourceTypeMetadata& resource_type_metadata,
3645
+ envoy_service_status_v3_PerXdsConfig* per_xds_config) {
3646
+ upb_strview kCdsTypeUrlUpb = upb_strview_makez(XdsApi::kCdsTypeUrl);
3647
+ auto* cluster_config_dump =
3648
+ envoy_service_status_v3_PerXdsConfig_mutable_cluster_config(
3649
+ per_xds_config, context.arena);
3650
+ envoy_admin_v3_ClustersConfigDump_set_version_info(
3651
+ cluster_config_dump,
3652
+ StdStringToUpbString(resource_type_metadata.version));
3653
+ for (auto& p : resource_type_metadata.resource_metadata_map) {
3654
+ absl::string_view name = p.first;
3655
+ const XdsApi::ResourceMetadata* meta = p.second;
3656
+ const upb_strview name_upb = StdStringToUpbString(name);
3657
+ auto* dynamic_cluster =
3658
+ envoy_admin_v3_ClustersConfigDump_add_dynamic_active_clusters(
3659
+ cluster_config_dump, context.arena);
3660
+ envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_client_status(
3661
+ dynamic_cluster, meta->client_status);
3662
+ auto* cluster_any =
3663
+ envoy_admin_v3_ClustersConfigDump_DynamicCluster_mutable_cluster(
3664
+ dynamic_cluster, context.arena);
3665
+ if (!meta->serialized_proto.empty()) {
3666
+ // Set in-effective clusters
3667
+ envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_version_info(
3668
+ dynamic_cluster, StdStringToUpbString(meta->version));
3669
+ envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_last_updated(
3670
+ dynamic_cluster, GrpcMillisToTimestamp(context, meta->update_time));
3671
+ google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb);
3672
+ google_protobuf_Any_set_value(
3673
+ cluster_any, StdStringToUpbString(meta->serialized_proto));
3674
+ } else {
3675
+ // If there isn't a working cluster, we still need to print the name.
3676
+ auto* cluster = envoy_config_cluster_v3_Cluster_new(context.arena);
3677
+ envoy_config_cluster_v3_Cluster_set_name(cluster, name_upb);
3678
+ size_t length;
3679
+ char* bytes = envoy_config_cluster_v3_Cluster_serialize(
3680
+ cluster, context.arena, &length);
3681
+ google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb);
3682
+ google_protobuf_Any_set_value(cluster_any,
3683
+ upb_strview_make(bytes, length));
3684
+ }
3685
+ if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
3686
+ // Set error_state if NACKED
3687
+ envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_error_state(
3688
+ dynamic_cluster, CreateUpdateFailureStateUpb(context, meta));
3689
+ }
3690
+ }
3691
+ }
3692
+
3693
+ void DumpEdsConfig(const EncodingContext& context,
3694
+ const XdsApi::ResourceTypeMetadata& resource_type_metadata,
3695
+ envoy_service_status_v3_PerXdsConfig* per_xds_config) {
3696
+ upb_strview kEdsTypeUrlUpb = upb_strview_makez(XdsApi::kEdsTypeUrl);
3697
+ auto* endpoint_config_dump =
3698
+ envoy_service_status_v3_PerXdsConfig_mutable_endpoint_config(
3699
+ per_xds_config, context.arena);
3700
+ for (auto& p : resource_type_metadata.resource_metadata_map) {
3701
+ absl::string_view name = p.first;
3702
+ const XdsApi::ResourceMetadata* meta = p.second;
3703
+ const upb_strview name_upb = StdStringToUpbString(name);
3704
+ auto* dynamic_endpoint =
3705
+ envoy_admin_v3_EndpointsConfigDump_add_dynamic_endpoint_configs(
3706
+ endpoint_config_dump, context.arena);
3707
+ envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_client_status(
3708
+ dynamic_endpoint, meta->client_status);
3709
+ auto* endpoint_any =
3710
+ envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_mutable_endpoint_config(
3711
+ dynamic_endpoint, context.arena);
3712
+ if (!meta->serialized_proto.empty()) {
3713
+ // Set in-effective endpoints
3714
+ envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_version_info(
3715
+ dynamic_endpoint, StdStringToUpbString(meta->version));
3716
+ envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_last_updated(
3717
+ dynamic_endpoint, GrpcMillisToTimestamp(context, meta->update_time));
3718
+ google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb);
3719
+ google_protobuf_Any_set_value(
3720
+ endpoint_any, StdStringToUpbString(meta->serialized_proto));
3721
+ } else {
3722
+ // If there isn't a working endpoint, we still need to print the name.
3723
+ auto* cluster_load_assignment =
3724
+ envoy_config_endpoint_v3_ClusterLoadAssignment_new(context.arena);
3725
+ envoy_config_endpoint_v3_ClusterLoadAssignment_set_cluster_name(
3726
+ cluster_load_assignment, name_upb);
3727
+ size_t length;
3728
+ char* bytes = envoy_config_endpoint_v3_ClusterLoadAssignment_serialize(
3729
+ cluster_load_assignment, context.arena, &length);
3730
+ google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb);
3731
+ google_protobuf_Any_set_value(endpoint_any,
3732
+ upb_strview_make(bytes, length));
3733
+ }
3734
+ if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
3735
+ // Set error_state if NACKED
3736
+ envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_error_state(
3737
+ dynamic_endpoint, CreateUpdateFailureStateUpb(context, meta));
3738
+ }
3739
+ }
3740
+ }
3741
+
3742
+ } // namespace
3743
+
3744
+ std::string XdsApi::AssembleClientConfig(
3745
+ const ResourceTypeMetadataMap& resource_type_metadata_map) {
3746
+ upb::Arena arena;
3747
+ // Create the ClientConfig for resource metadata from XdsClient
3748
+ auto* client_config = envoy_service_status_v3_ClientConfig_new(arena.ptr());
3749
+ // Fill-in the node information
3750
+ auto* node = envoy_service_status_v3_ClientConfig_mutable_node(client_config,
3751
+ arena.ptr());
3752
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
3753
+ true};
3754
+ PopulateNode(context, node_, build_version_, user_agent_name_, node);
3755
+ // Dump each xDS-type config into PerXdsConfig
3756
+ for (auto& p : resource_type_metadata_map) {
3757
+ absl::string_view type_url = p.first;
3758
+ const ResourceTypeMetadata& resource_type_metadata = p.second;
3759
+ if (type_url == kLdsTypeUrl) {
3760
+ auto* per_xds_config =
3761
+ envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
3762
+ context.arena);
3763
+ DumpLdsConfig(context, resource_type_metadata, per_xds_config);
3764
+ } else if (type_url == kRdsTypeUrl) {
3765
+ auto* per_xds_config =
3766
+ envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
3767
+ context.arena);
3768
+ DumpRdsConfig(context, resource_type_metadata, per_xds_config);
3769
+ } else if (type_url == kCdsTypeUrl) {
3770
+ auto* per_xds_config =
3771
+ envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
3772
+ context.arena);
3773
+ DumpCdsConfig(context, resource_type_metadata, per_xds_config);
3774
+ } else if (type_url == kEdsTypeUrl) {
3775
+ auto* per_xds_config =
3776
+ envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
3777
+ context.arena);
3778
+ DumpEdsConfig(context, resource_type_metadata, per_xds_config);
3779
+ } else {
3780
+ gpr_log(GPR_ERROR, "invalid type_url %s", std::string(type_url).c_str());
3781
+ return "";
3782
+ }
3783
+ }
3784
+ // Serialize the upb message to bytes
3785
+ size_t output_length;
3786
+ char* output = envoy_service_status_v3_ClientConfig_serialize(
3787
+ client_config, arena.ptr(), &output_length);
3788
+ return std::string(output, output_length);
3789
+ }
3790
+
2308
3791
  } // namespace grpc_core