diff --git a/envoy/1.20/patches/envoy/20221027-init.patch b/envoy/1.20/patches/envoy/20221027-init.patch new file mode 100644 index 000000000..c7a2fef1e --- /dev/null +++ b/envoy/1.20/patches/envoy/20221027-init.patch @@ -0,0 +1,15224 @@ +diff --git a/api/BUILD b/api/BUILD +index d8cffd4a48..59fc00be5e 100644 +--- a/api/BUILD ++++ b/api/BUILD +@@ -57,6 +57,7 @@ proto_library( + name = "v3_protos", + visibility = ["//visibility:public"], + deps = [ ++ "//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg", + "//contrib/envoy/extensions/filters/http/squash/v3:pkg", + "//contrib/envoy/extensions/filters/http/sxg/v3alpha:pkg", + "//contrib/envoy/extensions/filters/network/kafka_broker/v3:pkg", +diff --git a/api/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/BUILD b/api/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/BUILD +new file mode 100644 +index 0000000000..1c1a6f6b44 +--- /dev/null ++++ b/api/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/BUILD +@@ -0,0 +1,12 @@ ++# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. ++ ++load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") ++ ++licenses(["notice"]) # Apache 2 ++ ++api_proto_package( ++ deps = [ ++ "//envoy/config/core/v3:pkg", ++ "@com_github_cncf_udpa//udpa/annotations:pkg", ++ ], ++) +diff --git a/api/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.proto b/api/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.proto +new file mode 100644 +index 0000000000..b02031704c +--- /dev/null ++++ b/api/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.proto +@@ -0,0 +1,31 @@ ++syntax = "proto3"; ++ ++package envoy.extensions.custom_cluster_plugins.cluster_fallback.v3; ++ ++import "udpa/annotations/sensitive.proto"; ++import "udpa/annotations/status.proto"; ++import "validate/validate.proto"; ++ ++option java_package = "io.envoyproxy.envoy.extensions.custom_cluster_plugins.cluster_fallback.v3"; ++option java_outer_classname = "ClusterfallbackProto"; ++option java_multiple_files = true; ++option (udpa.annotations.file_status).package_version_status = ACTIVE; ++ ++message ClusterFallbackConfig { ++ ++ message ClusterConfig { ++ string routing_cluster = 1; ++ ++ repeated string fallback_clusters = 2; ++ } ++ ++ message WeightedClusterConfig { ++ repeated ClusterConfig config = 1; ++ } ++ ++ oneof config_specifier { ++ ClusterConfig cluster_config = 1; ++ ++ WeightedClusterConfig weighted_cluster_config = 2; ++ } ++} +diff --git a/api/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/BUILD b/api/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/BUILD +new file mode 100644 +index 0000000000..ee92fb6525 +--- /dev/null ++++ b/api/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/BUILD +@@ -0,0 +1,9 @@ ++# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. ++ ++load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") ++ ++licenses(["notice"]) # Apache 2 ++ ++api_proto_package( ++ deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"], ++) +diff --git a/api/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.proto b/api/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.proto +new file mode 100644 +index 0000000000..400fa0f4c2 +--- /dev/null ++++ b/api/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.proto +@@ -0,0 +1,119 @@ ++syntax = "proto3"; ++ ++package envoy.extensions.filters.http.http_dubbo_transcoder.v3; ++ ++import "google/protobuf/wrappers.proto"; ++ ++import "udpa/annotations/status.proto"; ++import "udpa/annotations/versioning.proto"; ++import "validate/validate.proto"; ++ ++option java_package = "io.envoyproxy.envoy.extensions.filters.http.http_dubbo_transcoder.v3"; ++option java_outer_classname = "HttpDubboTranscoderProto"; ++option java_multiple_files = true; ++option (udpa.annotations.file_status).package_version_status = ACTIVE; ++ ++// [#protodoc-title: Buffer] ++// Buffer :ref:`configuration overview `. ++// [#extension: envoy.filters.http.buffer] ++message HttpDubboTranscoder { ++ enum UrlUnescapeSpec { ++ // URL path parameters will not decode RFC 6570 reserved characters. ++ // For example, segment `%2f%23/%20%2523` is unescaped to `%2f%23/ %23`. ++ ALL_CHARACTERS_EXCEPT_RESERVED = 0; ++ ++ // URL path parameters will be fully URI-decoded except in ++ // cases of single segment matches in reserved expansion, where "%2F" will be ++ // left encoded. ++ // For example, segment `%2f%23/%20%2523` is unescaped to `%2f#/ %23`. ++ ALL_CHARACTERS_EXCEPT_SLASH = 1; ++ ++ // URL path parameters will be fully URI-decoded. ++ // For example, segment `%2f%23/%20%2523` is unescaped to `/#/ %23`. ++ ALL_CHARACTERS = 2; ++ } ++ ++ message RequestValidateOptions { ++ // default this trascoder will pass the request which contains unknown query paramters, ++ // if this option set to true, the request will be reject with 400 Bad Request. ++ bool reject_unknown_query_parameters = 1; ++ ++ bool reject_unknown_method = 2; ++ } ++ ++ message DubboMethodMapping { ++ enum MatchHttpMethodSpec { ++ ALL_GET = 0; ++ ALL_POST = 1; ++ ALL_PUT = 2; ++ ALL_DELETE = 3; ++ ALL_PATCH = 4; ++ } ++ ++ message ParameterMapping { ++ enum ExtractKeySpec { ++ ALL_QUERY_PARAMETER = 0; ++ ALL_HEADER = 1; ++ ALL_PATH = 2; ++ ALL_BODY = 3; ++ } ++ ++ ExtractKeySpec extract_key_spec = 1; ++ ++ string extract_key = 2; ++ ++ string mapping_type = 3; ++ } ++ ++ message PathMatcher { ++ string match_pattern = 1; ++ ++ MatchHttpMethodSpec match_http_method_spec = 2; ++ } ++ ++ message PassthroughSetting { ++ message PassthroughHeaders { ++ repeated string keys = 1; ++ } ++ ++ oneof headers_setting { ++ bool passthrough_all_headers = 1; ++ ++ PassthroughHeaders passthrough_headers = 2; ++ } ++ } ++ ++ string name = 1 [(validate.rules).string = {min_len: 1}]; ++ ++ PathMatcher path_matcher = 2; ++ ++ repeated ParameterMapping parameter_mapping = 3; ++ ++ PassthroughSetting passthrough_setting = 4; ++ } ++ ++ message DubboServiceMapping { ++ string name = 1 [(validate.rules).string = {min_len: 1}]; ++ ++ string version = 2; ++ ++ repeated DubboMethodMapping method_mapping = 3; ++ ++ string group = 4; ++ } ++ ++ // Configure the behavior when handling requests that cannot be transcoded. ++ // ++ // By default, the transcoder will silently pass through HTTP requests that are malformed. ++ // This includes requests with unknown query parameters, unregister paths, etc. ++ RequestValidateOptions request_validation_options = 2; ++ ++ // URL unescaping policy. ++ // This spec is only applied when extracting variable with multiple segments in the URL path. ++ // For example, in case of `/foo/{x=*}/bar/{y=prefix/*}/{z=**}` `x` variable is single segment and `y` and `z` are multiple segments. ++ // For a path with `/foo/first/bar/prefix/second/third/fourth`, `x=first`, `y=prefix/second`, `z=third/fourth`. ++ // If this setting is not specified, the value defaults to :ref:`ALL_CHARACTERS_EXCEPT_RESERVED`. ++ UrlUnescapeSpec url_unescape_spec = 3 [(validate.rules).enum = {defined_only: true}]; ++ ++ repeated DubboServiceMapping services_mapping = 4; ++} +diff --git a/api/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/BUILD b/api/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/BUILD +new file mode 100644 +index 0000000000..ee92fb6525 +--- /dev/null ++++ b/api/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/BUILD +@@ -0,0 +1,9 @@ ++# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. ++ ++load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") ++ ++licenses(["notice"]) # Apache 2 ++ ++api_proto_package( ++ deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"], ++) +diff --git a/api/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.proto b/api/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.proto +new file mode 100644 +index 0000000000..6adc905f6e +--- /dev/null ++++ b/api/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.proto +@@ -0,0 +1,17 @@ ++syntax = "proto3"; ++ ++package envoy.extensions.upstreams.http.dubbo_tcp.v3; ++ ++import "udpa/annotations/status.proto"; ++ ++option java_package = "io.envoyproxy.envoy.extensions.upstreams.http.dubbo_tcp.v3"; ++option java_outer_classname = "TcpConnectionPoolProto"; ++option java_multiple_files = true; ++option (udpa.annotations.file_status).package_version_status = ACTIVE; ++ ++// [#protodoc-title: Tcp Connection Pool] ++ ++// A connection pool which forwards downstream HTTP as TCP to upstream, ++// [#extension: envoy.upstreams.http.tcp] ++message DubboTcpConnectionPoolProto { ++} +diff --git a/api/envoy/config/route/v3/route.proto b/api/envoy/config/route/v3/route.proto +index e2bf52165b..3e806eeb57 100644 +--- a/api/envoy/config/route/v3/route.proto ++++ b/api/envoy/config/route/v3/route.proto +@@ -4,7 +4,6 @@ package envoy.config.route.v3; + + import "envoy/config/core/v3/base.proto"; + import "envoy/config/core/v3/config_source.proto"; +-import "envoy/config/core/v3/extension.proto"; + import "envoy/config/route/v3/route_components.proto"; + + import "google/protobuf/wrappers.proto"; +@@ -121,19 +120,12 @@ message RouteConfiguration { + // + google.protobuf.UInt32Value max_direct_response_body_size_bytes = 11; + +- // [#not-implemented-hide:] + // A list of plugins and their configurations which may be used by a +- // :ref:`envoy_v3_api_field_config.route.v3.RouteAction.cluster_specifier_plugin` ++ // :ref:`cluster specifier plugin name ` + // within the route. All *extension.name* fields in this list must be unique. + repeated ClusterSpecifierPlugin cluster_specifier_plugins = 12; + } + +-// Configuration for a cluster specifier plugin. +-message ClusterSpecifierPlugin { +- // The name of the plugin and its opaque configuration. +- core.v3.TypedExtensionConfig extension = 1; +-} +- + message Vhds { + option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.Vhds"; + +diff --git a/api/envoy/config/route/v3/route_components.proto b/api/envoy/config/route/v3/route_components.proto +index d25edd756d..80da2bdcef 100644 +--- a/api/envoy/config/route/v3/route_components.proto ++++ b/api/envoy/config/route/v3/route_components.proto +@@ -203,7 +203,7 @@ message FilterAction { + // + // Envoy supports routing on HTTP method via :ref:`header matching + // `. +-// [#next-free-field: 19] ++// [#next-free-field: 20] + message Route { + option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.Route"; + +@@ -301,6 +301,21 @@ message Route { + // If set, the bytes actually buffered will be the minimum value of this and the + // listener per_connection_buffer_limit_bytes. + google.protobuf.UInt32Value per_request_buffer_limit_bytes = 16; ++ ++ // The human readable prefix to use when emitting statistics for this endpoint. ++ // The statistics are rooted at vhost..route.. ++ // This should be set for highly critical ++ // endpoints that one wishes to get “per-route” statistics on. ++ // If not set, endpoint statistics are not generated. ++ // ++ // The emitted statistics are the same as those documented for :ref:`virtual clusters `. ++ // ++ // .. warning:: ++ // ++ // We do not recommend setting up a stat prefix for ++ // every application endpoint. This is both not easily maintainable and ++ // statistics use a non-trivial amount of memory(approximately 1KiB per route). ++ string stat_prefix = 19; + } + + // Compared to the :ref:`cluster ` field that specifies a +@@ -426,9 +441,32 @@ message WeightedCluster { + // configuration file will be used as the default weight. See the :ref:`runtime documentation + // ` for how key names map to the underlying implementation. + string runtime_key_prefix = 2; ++ ++ // Name of the cluster specifier plugin to use to determine the cluster for requests on this route. ++ // The cluster specifier plugin name must be defined in the associated ++ // :ref:`cluster specifier plugins ` ++ // in the :ref:`name ` field. ++ string cluster_specifier_plugin = 100; ++ ++ // Custom cluster specifier plugin configuration to use to determine the cluster for requests ++ // on this route. ++ ClusterSpecifierPlugin inline_cluster_specifier_plugin = 101; + } + +-// [#next-free-field: 14] ++// Configuration for a cluster specifier plugin. ++message ClusterSpecifierPlugin { ++ // The name of the plugin and its opaque configuration. ++ core.v3.TypedExtensionConfig extension = 1 [(validate.rules).message = {required: true}]; ++ ++ // If is_optional is not set or is set to false and the plugin defined by this message is not a ++ // supported type, the containing resource is NACKed. If is_optional is set to true, the resource ++ // would not be NACKed for this reason. In this case, routes referencing this plugin's name would ++ // not be treated as an illegal configuration, but would result in a failure if the route is ++ // selected. ++ bool is_optional = 2; ++} ++ ++// [#next-free-field: 15] + message RouteMatch { + option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RouteMatch"; + +@@ -607,7 +645,7 @@ message CorsPolicy { + core.v3.RuntimeFractionalPercent shadow_enabled = 10; + } + +-// [#next-free-field: 38] ++// [#next-free-field: 40] + message RouteAction { + option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RouteAction"; + +@@ -884,13 +922,15 @@ message RouteAction { + // for additional documentation. + WeightedCluster weighted_clusters = 3; + +- // [#not-implemented-hide:] +- // Name of the cluster specifier plugin to use to determine the cluster for +- // requests on this route. The plugin name must be defined in the associated +- // :ref:`envoy_v3_api_field_config.route.v3.RouteConfiguration.cluster_specifier_plugins` +- // in the +- // :ref:`envoy_v3_api_field_config.core.v3.TypedExtensionConfig.name` field. ++ // Name of the cluster specifier plugin to use to determine the cluster for requests on this route. ++ // The cluster specifier plugin name must be defined in the associated ++ // :ref:`cluster specifier plugins ` ++ // in the :ref:`name ` field. + string cluster_specifier_plugin = 37; ++ ++ // Custom cluster specifier plugin configuration to use to determine the cluster for requests ++ // on this route. ++ ClusterSpecifierPlugin inline_cluster_specifier_plugin = 39; + } + + // The HTTP status code to use when configured cluster is not found. +@@ -971,20 +1011,29 @@ message RouteAction { + + oneof host_rewrite_specifier { + // Indicates that during forwarding, the host header will be swapped with +- // this value. ++ // this value. Using this option will append the ++ // :ref:`config_http_conn_man_headers_x-forwarded-host` header if ++ // :ref:`append_x_forwarded_host ` ++ // is set. + string host_rewrite_literal = 6 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}]; + + // Indicates that during forwarding, the host header will be swapped with + // the hostname of the upstream host chosen by the cluster manager. This + // option is applicable only when the destination cluster for a route is of +- // type *strict_dns* or *logical_dns*. Setting this to true with other cluster +- // types has no effect. ++ // type *strict_dns* or *logical_dns*. Setting this to true with other cluster types ++ // has no effect. Using this option will append the ++ // :ref:`config_http_conn_man_headers_x-forwarded-host` header if ++ // :ref:`append_x_forwarded_host ` ++ // is set. + google.protobuf.BoolValue auto_host_rewrite = 7; + + // Indicates that during forwarding, the host header will be swapped with the content of given + // downstream or :ref:`custom ` header. +- // If header value is empty, host header is left intact. ++ // If header value is empty, host header is left intact. Using this option will append the ++ // :ref:`config_http_conn_man_headers_x-forwarded-host` header if ++ // :ref:`append_x_forwarded_host ` ++ // is set. + // + // .. attention:: + // +@@ -1000,6 +1049,10 @@ message RouteAction { + // Indicates that during forwarding, the host header will be swapped with + // the result of the regex substitution executed on path value with query and fragment removed. + // This is useful for transitioning variable content between path segment and subdomain. ++ // Using this option will append the ++ // :ref:`config_http_conn_man_headers_x-forwarded-host` header if ++ // :ref:`append_x_forwarded_host ` ++ // is set. + // + // For example with the following config: + // +@@ -1015,6 +1068,15 @@ message RouteAction { + type.matcher.v3.RegexMatchAndSubstitute host_rewrite_path_regex = 35; + } + ++ // If set, then a host rewrite action (one of ++ // :ref:`host_rewrite_literal `, ++ // :ref:`auto_host_rewrite `, ++ // :ref:`host_rewrite_header `, or ++ // :ref:`host_rewrite_path_regex `) ++ // causes the original value of the host header, if any, to be appended to the ++ // :ref:`config_http_conn_man_headers_x-forwarded-host` HTTP header. ++ bool append_x_forwarded_host = 38; ++ + // Specifies the upstream timeout for the route. If not specified, the default is 15s. This + // spans between the point at which the entire downstream request (i.e. end-of-stream) has been + // processed and when the upstream response has been completely processed. A value of 0 will +@@ -1169,6 +1231,8 @@ message RouteAction { + + // Specifies the maximum stream duration for this route. + MaxStreamDuration max_stream_duration = 36; ++ ++ InternalActiveRedirectPolicy internal_active_redirect_policy = 1000; + } + + // HTTP retry :ref:`architecture overview `. +@@ -2076,6 +2140,109 @@ message InternalRedirectPolicy { + bool allow_cross_scheme_redirect = 4; + } + ++// Redirects to the specified URI based on the response code. ++// [#next-free-field: 19] ++message InternalActiveRedirectPolicy { ++ // [#next-free-field: 18] ++ message RedirectPolicy { ++ // An internal redirect is not handled, unless the number of previous internal redirects that a ++ // downstream request has encountered is lower than this value. ++ // In the case where a downstream request is bounced among multiple routes by internal redirect, ++ // the first route that hits this threshold, or does not set :ref:`internal_redirect_policy ++ // ` ++ // will pass the redirect back to downstream. ++ // ++ // If not specified, at most one redirect will be followed. ++ google.protobuf.UInt32Value max_internal_redirects = 10; ++ ++ // Defines what upstream response codes are allowed to trigger internal redirect. ++ // All response codes support redirection except 200. ++ repeated uint32 redirect_response_codes = 11 [(validate.rules).repeated = {max_items: 50}]; ++ ++ // The URI of the redirect. ++ oneof redirect_url_rewrite_specifier { ++ option (validate.required) = true; ++ ++ string redirect_url = 12 [(validate.rules).string = {min_len: 1}]; ++ ++ type.matcher.v3.RegexMatchAndSubstitute redirect_url_rewrite_regex = 13; ++ } ++ ++ // Specifies a list of predicates that are queried when an upstream response is deemed ++ // to trigger an internal redirect by all other criteria. Any predicate in the list can reject ++ // the redirect, causing the response to be proxied to downstream. ++ repeated core.v3.TypedExtensionConfig predicates = 14; ++ ++ // Allow internal redirect to follow a target URI with a different scheme than the value of ++ // x-forwarded-proto. The default is false. ++ bool allow_cross_scheme_redirect = 15; ++ ++ // HTTP headers to add to a local reply. This allows the response mapper to append, to add ++ // or to override headers of any local reply before it is sent to a downstream client. ++ repeated core.v3.HeaderValueOption request_headers_to_add = 16 ++ [(validate.rules).repeated = {max_items: 1000}]; ++ ++ // Indicates that during forwarding, the host header will be swapped with ++ // this value. ++ string host_rewrite_literal = 17 ++ [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}]; ++ ++ // If true, the host name in the downstream request is used for redirection. ++ bool forced_use_original_host = 20; ++ ++ bool forced_add_header_before_route_matcher = 22; ++ } ++ ++ // An internal redirect is not handled, unless the number of previous internal redirects that a ++ // downstream request has encountered is lower than this value. ++ // In the case where a downstream request is bounced among multiple routes by internal redirect, ++ // the first route that hits this threshold, or does not set :ref:`internal_redirect_policy ++ // ` ++ // will pass the redirect back to downstream. ++ // ++ // If not specified, at most one redirect will be followed. ++ google.protobuf.UInt32Value max_internal_redirects = 1; ++ ++ // Defines what upstream response codes are allowed to trigger internal redirect. ++ // All response codes support redirection except 200. ++ repeated uint32 redirect_response_codes = 2 [(validate.rules).repeated = {max_items: 50}]; ++ ++ // The URI of the redirect. ++ oneof redirect_url_rewrite_specifier { ++ //option (validate.required) = true; ++ ++ string redirect_url = 7 [(validate.rules).string = {min_len: 1}]; ++ ++ type.matcher.v3.RegexMatchAndSubstitute redirect_url_rewrite_regex = 8; ++ } ++ ++ // Specifies a list of predicates that are queried when an upstream response is deemed ++ // to trigger an internal redirect by all other criteria. Any predicate in the list can reject ++ // the redirect, causing the response to be proxied to downstream. ++ repeated core.v3.TypedExtensionConfig predicates = 4; ++ ++ // Allow internal redirect to follow a target URI with a different scheme than the value of ++ // x-forwarded-proto. The default is false. ++ bool allow_cross_scheme_redirect = 5; ++ ++ // HTTP headers to add to a local reply. This allows the response mapper to append, to add ++ // or to override headers of any local reply before it is sent to a downstream client. ++ repeated core.v3.HeaderValueOption request_headers_to_add = 6 ++ [(validate.rules).repeated = {max_items: 1000}]; ++ ++ // Indicates that during forwarding, the host header will be swapped with ++ // this value. ++ string host_rewrite_literal = 9 ++ [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}]; ++ ++ // If true, the host name in the downstream request is used for redirection. ++ bool forced_use_original_host = 19; ++ ++ bool forced_add_header_before_route_matcher = 21; ++ ++ repeated RedirectPolicy policies = 18; ++} ++ + // A simple wrapper for an HTTP filter config. This is intended to be used as a wrapper for the + // map value in + // :ref:`VirtualHost.typed_per_filter_config`, +diff --git a/api/versioning/BUILD b/api/versioning/BUILD +index 8febd11d20..13a58e1d11 100644 +--- a/api/versioning/BUILD ++++ b/api/versioning/BUILD +@@ -9,6 +9,7 @@ proto_library( + name = "active_protos", + visibility = ["//visibility:public"], + deps = [ ++ "//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg", + "//contrib/envoy/extensions/filters/http/squash/v3:pkg", + "//contrib/envoy/extensions/filters/http/sxg/v3alpha:pkg", + "//contrib/envoy/extensions/filters/network/kafka_broker/v3:pkg", +diff --git a/bazel/BUILD b/bazel/BUILD +index 3b22ffc8ff..1553e76a9d 100644 +--- a/bazel/BUILD ++++ b/bazel/BUILD +@@ -539,6 +539,13 @@ config_setting( + define_values = {"FUZZING_ENGINE": "oss-fuzz"}, + ) + ++# By default we enable AliMesh build. If want to build community ++# version then build Envoy with flag of '--define alimesh=false'. ++config_setting( ++ name = "alimesh", ++ values = {"define": "alimesh=false"}, ++) ++ + alias( + name = "fuzzing_engine", + actual = select({ +diff --git a/bazel/envoy_binary.bzl b/bazel/envoy_binary.bzl +index 6ea24b9888..ad9375d9b1 100644 +--- a/bazel/envoy_binary.bzl ++++ b/bazel/envoy_binary.bzl +@@ -8,6 +8,7 @@ load( + "envoy_external_dep_path", + "envoy_stdlib_deps", + "tcmalloc_external_dep", ++ "envoy_select_alimesh", + ) + + # Envoy C++ binary targets should be specified with this function. +diff --git a/bazel/envoy_internal.bzl b/bazel/envoy_internal.bzl +index 9c5130f15e..20d80977f2 100644 +--- a/bazel/envoy_internal.bzl ++++ b/bazel/envoy_internal.bzl +@@ -122,6 +122,7 @@ def envoy_copts(repository, test = False): + envoy_select_enable_http3(["-DENVOY_ENABLE_QUIC"], repository) + \ + _envoy_select_perf_annotation(["-DENVOY_PERF_ANNOTATION"]) + \ + envoy_select_google_grpc(["-DENVOY_GOOGLE_GRPC"], repository) + \ ++ envoy_select_alimesh(["-DALIMESH"]) + \ + _envoy_select_path_normalization_by_default(["-DENVOY_NORMALIZE_PATH_BY_DEFAULT"], repository) + + # References to Envoy external dependencies should be wrapped with this function. +@@ -179,3 +180,9 @@ def _envoy_select_perf_annotation(xs): + "@envoy//bazel:enable_perf_annotation": xs, + "//conditions:default": [], + }) ++ ++def envoy_select_alimesh(xs): ++ return select({ ++ "@envoy//bazel:alimesh": [], ++ "//conditions:default": xs, ++ }) +diff --git a/bazel/envoy_library.bzl b/bazel/envoy_library.bzl +index 5b1d674483..3a2204083c 100644 +--- a/bazel/envoy_library.bzl ++++ b/bazel/envoy_library.bzl +@@ -93,12 +93,18 @@ def envoy_cc_library( + tags = [], + deps = [], + strip_include_prefix = None, ++ alimesh_deps = [], + include_prefix = None, + textual_hdrs = None, + defines = []): + if tcmalloc_dep: + deps += tcmalloc_external_deps(repository) + ++ deps = deps + select({ ++ "@envoy//bazel:alimesh": [], ++ "//conditions:default": alimesh_deps, ++ }) ++ + cc_library( + name = name, + srcs = srcs, +diff --git a/bazel/external/wee8.genrule_cmd b/bazel/external/wee8.genrule_cmd +index 7b175a1f20..a16e6112f8 100644 +--- a/bazel/external/wee8.genrule_cmd ++++ b/bazel/external/wee8.genrule_cmd +@@ -99,6 +99,8 @@ WEE8_BUILD_ARGS+=" v8_use_external_startup_data=false" + # Disable read-only heap, since it's leaky and HEAPCHECK complains about it. + # TODO(PiotrSikora): remove when fixed upstream. + WEE8_BUILD_ARGS+=" v8_enable_shared_ro_heap=false" ++# Disable pointer compression (limits the maximum number of WasmVMs). ++WEE8_BUILD_ARGS+=" v8_enable_pointer_compression=false" + + # Set target architecture. + if [[ $${ARCH} == "x86_64" ]]; then +diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl +index c642f6e375..6aba260762 100644 +--- a/bazel/repositories.bzl ++++ b/bazel/repositories.bzl +@@ -1,5 +1,7 @@ + load(":dev_binding.bzl", "envoy_dev_binding") + load(":genrule_repository.bzl", "genrule_repository") ++load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") ++load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository") + load("@envoy_api//bazel:envoy_http_archive.bzl", "envoy_http_archive") + load("@envoy_api//bazel:external_deps.bzl", "load_repository_locations") + load(":repository_locations.bzl", "REPOSITORY_LOCATIONS_SPEC") +@@ -7,6 +9,8 @@ load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_languag + + PPC_SKIP_TARGETS = ["envoy.filters.http.lua"] + ++DARWIN_SKIP_TARGETS = [] ++ + WINDOWS_SKIP_TARGETS = [ + "envoy.filters.http.sxg", + "envoy.tracers.dynamic_ot", +@@ -573,6 +577,10 @@ def _com_github_alibaba_hessian2_codec(): + name = "hessian2_codec_codec_impl", + actual = "@com_github_alibaba_hessian2_codec//hessian2:codec_impl_lib", + ) ++ native.bind( ++ name = "hessian2_codec_object_impl", ++ actual = "@com_github_alibaba_hessian2_codec//hessian2:object_lib", ++ ) + + def _com_github_ncopa_suexec(): + external_http_archive( +diff --git a/ci/run_clang_tidy.sh b/ci/run_clang_tidy.sh +index 0aca2629f3..a485c4a564 100755 +--- a/ci/run_clang_tidy.sh ++++ b/ci/run_clang_tidy.sh +@@ -98,9 +98,12 @@ function run_clang_tidy_diff() { + git diff "$1" | filter_excludes | \ + python3 "${LLVM_PREFIX}/share/clang/clang-tidy-diff.py" \ + -clang-tidy-binary="${CLANG_TIDY}" \ +- -export-fixes="${FIX_YAML}" -j "${NUM_CPUS:-0}" -p 1 -quiet ++ -export-fixes="${FIX_YAML}" -j "${NUM_CPUS:-0}" -p 1 -quiet \ ++ -iregex="^(?!.*(${CLANG_TIDY_SKIL_KEYWORD})).*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)" + } + ++export CLANG_TIDY_SKIL_KEYWORD="egds|data_restorer|alimesh.*mocks|unit_route|test/.*eagleeye" ++ + if [[ $# -gt 0 ]]; then + echo "Running clang-tidy on: $*" + run_clang_tidy "$@" +diff --git a/contrib/common/active_redirect/source/BUILD b/contrib/common/active_redirect/source/BUILD +new file mode 100644 +index 0000000000..8a770f9b26 +--- /dev/null ++++ b/contrib/common/active_redirect/source/BUILD +@@ -0,0 +1,34 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_library", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_library( ++ name = "active_redirect_policy_lib", ++ srcs = ["active_redirect_policy_impl.cc"], ++ hdrs = ["active_redirect_policy_impl.h"], ++ external_deps = ["abseil_optional"], ++ visibility = ["//visibility:public"], ++ deps = [ ++ "//contrib/envoy/http:active_redirect_policy_interface", ++ "//envoy/http:header_map_interface", ++ "//envoy/router:router_interface", ++ "//source/common/common:empty_string", ++ "//source/common/common:utility_lib", ++ "//source/common/config:utility_lib", ++ "//source/common/http:header_utility_lib", ++ "//source/common/http:headers_lib", ++ "//source/common/http:path_utility_lib", ++ "//source/common/http:utility_lib", ++ "//source/common/protobuf:utility_lib", ++ "//source/common/router:header_parser_lib", ++ "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ++ "@envoy_api//envoy/config/route/v3:pkg_cc_proto", ++ "@envoy_api//envoy/type/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/common/active_redirect/source/active_redirect_policy_impl.cc b/contrib/common/active_redirect/source/active_redirect_policy_impl.cc +new file mode 100644 +index 0000000000..03d9bdeab2 +--- /dev/null ++++ b/contrib/common/active_redirect/source/active_redirect_policy_impl.cc +@@ -0,0 +1,225 @@ ++#include "contrib/common/active_redirect/source/active_redirect_policy_impl.h" ++ ++#include ++#include ++ ++#include "source/common/common/empty_string.h" ++#include "source/common/common/regex.h" ++#include "source/common/common/utility.h" ++#include "source/common/config/utility.h" ++#include "source/common/http/path_utility.h" ++ ++namespace Envoy { ++namespace Router { ++ ++InternalActiveRedirectPolicyImpl::InternalActiveRedirectPolicyImpl( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy& policy_config, ++ ProtobufMessage::ValidationVisitor& validator, absl::string_view current_route_name) ++ : current_route_name_(current_route_name), ++ redirect_response_codes_(buildRedirectResponseCodes(policy_config)), ++ max_internal_redirects_( ++ PROTOBUF_GET_WRAPPED_OR_DEFAULT(policy_config, max_internal_redirects, 1)), ++ enabled_(true), allow_cross_scheme_redirect_(policy_config.allow_cross_scheme_redirect()), ++ redirect_url_(policy_config.redirect_url()), ++ request_headers_parser_(HeaderParser::configure(policy_config.request_headers_to_add())), ++ redirect_url_rewrite_regex_( ++ policy_config.has_redirect_url_rewrite_regex() ++ ? Regex::Utility::parseRegex(policy_config.redirect_url_rewrite_regex().pattern()) ++ : nullptr), ++ redirect_url_rewrite_regex_substitution_( ++ policy_config.has_redirect_url_rewrite_regex() ++ ? policy_config.redirect_url_rewrite_regex().substitution() ++ : ""), ++ host_rewrite_(policy_config.host_rewrite_literal()), ++ forced_use_original_host_(policy_config.forced_use_original_host()), ++ forced_add_header_before_route_matcher_(policy_config.forced_add_header_before_route_matcher()) { ++ for (const auto& predicate : policy_config.predicates()) { ++ auto& factory = ++ Envoy::Config::Utility::getAndCheckFactory(predicate); ++ auto config = factory.createEmptyConfigProto(); ++ Envoy::Config::Utility::translateOpaqueConfig(predicate.typed_config(), validator, *config); ++ predicate_factories_.emplace_back(&factory, std::move(config)); ++ } ++} ++ ++InternalActiveRedirectPolicyImpl::InternalActiveRedirectPolicyImpl( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy::RedirectPolicy& policy_config, ++ ProtobufMessage::ValidationVisitor& validator, absl::string_view current_route_name) ++ : current_route_name_(current_route_name), ++ redirect_response_codes_(buildRedirectResponseCodes(policy_config)), ++ max_internal_redirects_( ++ PROTOBUF_GET_WRAPPED_OR_DEFAULT(policy_config, max_internal_redirects, 1)), ++ enabled_(true), allow_cross_scheme_redirect_(policy_config.allow_cross_scheme_redirect()), ++ redirect_url_(policy_config.redirect_url()), ++ request_headers_parser_(HeaderParser::configure(policy_config.request_headers_to_add())), ++ redirect_url_rewrite_regex_( ++ policy_config.has_redirect_url_rewrite_regex() ++ ? Regex::Utility::parseRegex(policy_config.redirect_url_rewrite_regex().pattern()) ++ : nullptr), ++ redirect_url_rewrite_regex_substitution_( ++ policy_config.has_redirect_url_rewrite_regex() ++ ? policy_config.redirect_url_rewrite_regex().substitution() ++ : ""), ++ host_rewrite_(policy_config.host_rewrite_literal()) { ++ for (const auto& predicate : policy_config.predicates()) { ++ auto& factory = ++ Envoy::Config::Utility::getAndCheckFactory(predicate); ++ auto config = factory.createEmptyConfigProto(); ++ Envoy::Config::Utility::translateOpaqueConfig(predicate.typed_config(), validator, *config); ++ predicate_factories_.emplace_back(&factory, std::move(config)); ++ } ++} ++ ++std::vector ++InternalActiveRedirectPolicyImpl::predicates() const { ++ std::vector predicates; ++ for (const auto& predicate_factory : predicate_factories_) { ++ predicates.emplace_back(predicate_factory.first->createInternalRedirectPredicate( ++ *predicate_factory.second, current_route_name_)); ++ } ++ return predicates; ++} ++ ++absl::flat_hash_set InternalActiveRedirectPolicyImpl::buildRedirectResponseCodes( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy& policy_config) const { ++ if (policy_config.redirect_response_codes_size() == 0) { ++ return absl::flat_hash_set{}; ++ } ++ ++ absl::flat_hash_set ret; ++ std::for_each(policy_config.redirect_response_codes().begin(), ++ policy_config.redirect_response_codes().end(), [&ret](uint32_t response_code) { ++ const absl::flat_hash_set valid_redirect_response_code = { ++ 301, 302, 303, 307, 308, 200}; ++ if (!valid_redirect_response_code.contains(response_code)) { ++ ret.insert(static_cast(response_code)); ++ } ++ }); ++ return ret; ++} ++ ++absl::flat_hash_set InternalActiveRedirectPolicyImpl::buildRedirectResponseCodes( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy::RedirectPolicy& policy_config) ++ const { ++ if (policy_config.redirect_response_codes_size() == 0) { ++ return absl::flat_hash_set{}; ++ } ++ ++ absl::flat_hash_set ret; ++ std::for_each(policy_config.redirect_response_codes().begin(), ++ policy_config.redirect_response_codes().end(), [&ret](uint32_t response_code) { ++ const absl::flat_hash_set valid_redirect_response_code = { ++ 301, 302, 303, 307, 308, 200}; ++ if (!valid_redirect_response_code.contains(response_code)) { ++ ret.insert(static_cast(response_code)); ++ } ++ }); ++ return ret; ++} ++ ++void InternalActiveRedirectPolicyImpl::evaluateHeaders( ++ Http::HeaderMap& headers, const StreamInfo::StreamInfo* stream_info) const { ++ request_headers_parser_->evaluateHeaders(headers, stream_info); ++ if (!host_rewrite_.empty()) { ++ Http::RequestHeaderMap& request_headers = dynamic_cast(headers); ++ request_headers.setHost(host_rewrite_); ++ } ++} ++ ++std::string ++InternalActiveRedirectPolicyImpl::redirectUrl(absl::optional current_path) const { ++ if (!redirect_url_.empty()) { ++ ENVOY_LOG(debug, "The redirect url: {}", redirect_url_); ++ return redirect_url_; ++ } ++ ++ RELEASE_ASSERT(current_path.has_value(), ++ "The internal redirect address uses a regular expression, but does not pass in " ++ "the current path value"); ++ auto just_path(Http::PathUtil::removeQueryAndFragment(current_path.value())); ++ return redirect_url_rewrite_regex_->replaceAll(just_path, ++ redirect_url_rewrite_regex_substitution_); ++} ++ ++bool InternalActiveRedirectPolicyImpl::forcedUseOriginalHost() const { ++ return forced_use_original_host_; ++} ++ ++InternalActiveRedirectPoliciesImpl::InternalActiveRedirectPoliciesImpl( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy& policy_config, ++ ProtobufMessage::ValidationVisitor& validator, absl::string_view current_route_name) { ++ if (policy_config.policies().empty() && !policy_config.redirect_response_codes().empty()) { ++ ENVOY_LOG(warn, "Please configure the redirection policy using the Policies field, the old " ++ "configuration will be deprecated"); ++ auto policy = std::make_unique(policy_config, validator, ++ current_route_name); ++ policies_.emplace_back(std::move(policy)); ++ } ++ ++ for (const auto& policy : policy_config.policies()) { ++ auto policy_impl = ++ std::make_unique(policy, validator, current_route_name); ++ policies_.emplace_back(std::move(policy_impl)); ++ } ++ ++ if (policies_.empty()) { ++ ENVOY_LOG(warn, "No redirection policy is currently configured. A default value is generated"); ++ auto policy_impl = std::make_unique(); ++ policies_.emplace_back(std::move(policy_impl)); ++ } ++} ++ ++InternalActiveRedirectPoliciesImpl::InternalActiveRedirectPoliciesImpl() { ++ auto policy_impl = std::make_unique(); ++ policies_.emplace_back(std::move(policy_impl)); ++} ++ ++std::vector ++InternalActiveRedirectPoliciesImpl::predicates() const { ++ return policies_.at(current_policy_index_)->predicates(); ++} ++ ++void InternalActiveRedirectPoliciesImpl::evaluateHeaders( ++ Http::HeaderMap& headers, const StreamInfo::StreamInfo* stream_info) const { ++ return policies_.at(current_policy_index_)->evaluateHeaders(headers, stream_info); ++} ++ ++std::string ++InternalActiveRedirectPoliciesImpl::redirectUrl(absl::optional current_path) const { ++ return policies_.at(current_policy_index_)->redirectUrl(current_path); ++} ++ ++bool InternalActiveRedirectPoliciesImpl::enabled() const { ++ return policies_.at(current_policy_index_)->enabled(); ++} ++ ++bool InternalActiveRedirectPoliciesImpl::shouldRedirectForResponseCode( ++ const Http::Code& response_code) const { ++ for (ActiveRedirectPolicies::size_type i = 0; i < policies_.size(); i++) { ++ if (policies_.at(i)->shouldRedirectForResponseCode(response_code)) { ++ current_policy_index_ = i; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++uint32_t InternalActiveRedirectPoliciesImpl::maxInternalRedirects() const { ++ return policies_.at(current_policy_index_)->maxInternalRedirects(); ++} ++ ++bool InternalActiveRedirectPoliciesImpl::isCrossSchemeRedirectAllowed() const { ++ return policies_.at(current_policy_index_)->isCrossSchemeRedirectAllowed(); ++} ++ ++bool InternalActiveRedirectPoliciesImpl::forcedUseOriginalHost() const { ++ return policies_.at(current_policy_index_)->forcedUseOriginalHost(); ++} ++ ++bool InternalActiveRedirectPoliciesImpl::forcedAddHeaderBeforeRouteMatcher() const { ++ return policies_.at(current_policy_index_)->forcedAddHeaderBeforeRouteMatcher(); ++} ++ ++} // namespace Router ++} // namespace Envoy +diff --git a/contrib/common/active_redirect/source/active_redirect_policy_impl.h b/contrib/common/active_redirect/source/active_redirect_policy_impl.h +new file mode 100644 +index 0000000000..5eae0dbde5 +--- /dev/null ++++ b/contrib/common/active_redirect/source/active_redirect_policy_impl.h +@@ -0,0 +1,118 @@ ++#pragma once ++ ++#include ++#include ++ ++#include "envoy/config/core/v3/base.pb.h" ++#include "envoy/config/route/v3/route.pb.h" ++#include "envoy/config/route/v3/route_components.pb.h" ++#include "envoy/type/v3/percent.pb.h" ++ ++#include "source/common/http/header_utility.h" ++#include "source/common/protobuf/protobuf.h" ++#include "source/common/protobuf/utility.h" ++#include "source/common/router/header_parser.h" ++ ++#include "absl/container/node_hash_map.h" ++#include "absl/types/optional.h" ++#include "contrib/envoy/http/active_redirect_policy.h" ++ ++namespace Envoy { ++namespace Router { ++ ++/** ++ * Implementation of InternalActiveRedirectPolicyImpl that reads from the proto ++ * InternalActiveRedirectPolicyImpl of the RouteAction. ++ */ ++class InternalActiveRedirectPolicyImpl : public InternalActiveRedirectPolicy, ++ Logger::Loggable { ++public: ++ // Constructor that enables internal redirect with policy_config controlling the configurable ++ // behaviors. ++ explicit InternalActiveRedirectPolicyImpl( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy& policy_config, ++ ProtobufMessage::ValidationVisitor& validator, absl::string_view current_route_name); ++ explicit InternalActiveRedirectPolicyImpl( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy::RedirectPolicy& policy_config, ++ ProtobufMessage::ValidationVisitor& validator, absl::string_view current_route_name); ++ // Default constructor that disables internal redirect. ++ InternalActiveRedirectPolicyImpl() = default; ++ ++ bool enabled() const override { return enabled_; } ++ ++ bool shouldRedirectForResponseCode(const Http::Code& response_code) const override { ++ return redirect_response_codes_.contains(response_code); ++ } ++ ++ std::vector predicates() const override; ++ ++ uint32_t maxInternalRedirects() const override { return max_internal_redirects_; } ++ ++ bool isCrossSchemeRedirectAllowed() const override { return allow_cross_scheme_redirect_; } ++ ++ void evaluateHeaders(Http::HeaderMap& headers, ++ const StreamInfo::StreamInfo* stream_info) const override; ++ ++ std::string redirectUrl(absl::optional current_path = absl::nullopt) const override; ++ ++ bool forcedUseOriginalHost() const override; ++ bool forcedAddHeaderBeforeRouteMatcher() const override { ++ return forced_add_header_before_route_matcher_; ++ } ++ ++private: ++ absl::flat_hash_set buildRedirectResponseCodes( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy& policy_config) const; ++ absl::flat_hash_set buildRedirectResponseCodes( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy::RedirectPolicy& policy_config) ++ const; ++ ++ const std::string current_route_name_; ++ const absl::flat_hash_set redirect_response_codes_; ++ const uint32_t max_internal_redirects_{1}; ++ const bool enabled_{false}; ++ const bool allow_cross_scheme_redirect_{false}; ++ const std::string redirect_url_; ++ const HeaderParserPtr request_headers_parser_; ++ const Regex::CompiledMatcherPtr redirect_url_rewrite_regex_; ++ const std::string redirect_url_rewrite_regex_substitution_; ++ const std::string host_rewrite_; ++ const bool forced_use_original_host_{false}; ++ const bool forced_add_header_before_route_matcher_{false}; ++ ++ std::vector> ++ predicate_factories_; ++}; ++ ++using InternalActiveRedirectPolicySharedPtr = std::shared_ptr; ++using ActiveRedirectPolicies = std::vector; ++ ++class InternalActiveRedirectPoliciesImpl : public InternalActiveRedirectPolicy, ++ Logger::Loggable { ++public: ++ // Constructor that enables internal redirect with policy_config controlling the configurable ++ // behaviors. ++ explicit InternalActiveRedirectPoliciesImpl( ++ const envoy::config::route::v3::InternalActiveRedirectPolicy& policy_config, ++ ProtobufMessage::ValidationVisitor& validator, absl::string_view current_route_name); ++ // Default constructor that disables internal redirect. ++ InternalActiveRedirectPoliciesImpl(); ++ ++ bool enabled() const override; ++ bool shouldRedirectForResponseCode(const Http::Code& response_code) const override; ++ std::vector predicates() const override; ++ uint32_t maxInternalRedirects() const override; ++ bool isCrossSchemeRedirectAllowed() const override; ++ void evaluateHeaders(Http::HeaderMap& headers, ++ const StreamInfo::StreamInfo* stream_info) const override; ++ std::string redirectUrl(absl::optional current_path = absl::nullopt) const override; ++ bool forcedUseOriginalHost() const override; ++ bool forcedAddHeaderBeforeRouteMatcher() const override; ++ ++private: ++ ActiveRedirectPolicies policies_; ++ mutable ActiveRedirectPolicies::size_type current_policy_index_{0}; ++}; ++ ++} // namespace Router ++} // namespace Envoy +diff --git a/contrib/common/localtime_formatter/source/BUILD b/contrib/common/localtime_formatter/source/BUILD +new file mode 100644 +index 0000000000..e421762231 +--- /dev/null ++++ b/contrib/common/localtime_formatter/source/BUILD +@@ -0,0 +1,29 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_library", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_library( ++ name = "substitution_formatter_lib", ++ srcs = ["substitution_formatter.cc"], ++ hdrs = ["substitution_formatter.h"], ++ external_deps = ["abseil_str_format"], ++ visibility = ["//visibility:public"], ++ deps = [ ++ "//envoy/formatter:substitution_formatter_interface", ++ "//envoy/stream_info:stream_info_interface", ++ "//source/common/common:assert_lib", ++ "//source/common/common:utility_lib", ++ "//source/common/config:metadata_lib", ++ "//source/common/grpc:common_lib", ++ "//source/common/http:utility_lib", ++ "//source/common/protobuf:message_validator_lib", ++ "//source/common/stream_info:utility_lib", ++ "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/common/localtime_formatter/source/substitution_formatter.cc b/contrib/common/localtime_formatter/source/substitution_formatter.cc +new file mode 100644 +index 0000000000..c643526f84 +--- /dev/null ++++ b/contrib/common/localtime_formatter/source/substitution_formatter.cc +@@ -0,0 +1,84 @@ ++#include "contrib/common/localtime_formatter/source/substitution_formatter.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "envoy/config/core/v3/base.pb.h" ++ ++#include "source/common/api/os_sys_calls_impl.h" ++#include "source/common/common/assert.h" ++#include "source/common/common/empty_string.h" ++#include "source/common/common/fmt.h" ++#include "source/common/common/utility.h" ++#include "source/common/config/metadata.h" ++#include "source/common/grpc/common.h" ++#include "source/common/grpc/status.h" ++#include "source/common/http/utility.h" ++#include "source/common/protobuf/message_validator_impl.h" ++#include "source/common/protobuf/utility.h" ++#include "source/common/stream_info/utility.h" ++ ++#include "absl/strings/str_split.h" ++#include "fmt/format.h" ++ ++namespace Envoy { ++namespace Formatter { ++ ++LocalStartTimeFormatter::LocalStartTimeFormatter(const std::string& token) ++ : date_formatter_(parseFormat(token, sizeof("LOCAL_START_TIME(") - 1)) {} ++ ++absl::optional LocalStartTimeFormatter::format( ++ const Http::RequestHeaderMap&, const Http::ResponseHeaderMap&, const Http::ResponseTrailerMap&, ++ const StreamInfo::StreamInfo& stream_info, absl::string_view) const { ++ return DateTimeFormatter::fromTime(stream_info.startTime(), absl::LocalTimeZone()); ++} ++ ++ProtobufWkt::Value LocalStartTimeFormatter::formatValue( ++ const Http::RequestHeaderMap& request_headers, const Http::ResponseHeaderMap& response_headers, ++ const Http::ResponseTrailerMap& response_trailers, const StreamInfo::StreamInfo& stream_info, ++ absl::string_view local_reply_body) const { ++ return ValueUtil::optionalStringValue( ++ format(request_headers, response_headers, response_trailers, stream_info, local_reply_body)); ++} ++ ++std::string LocalStartTimeFormatter::DateTimeFormatter::fromTime(const SystemTime& system_time, ++ absl::TimeZone time_zone) { ++ static const std::string DefaultDateFormat = "%Y-%m-%dT%H:%M:%E3SZ"; ++ ++ struct CachedTime { ++ std::chrono::seconds epoch_time_seconds; ++ std::string formatted_time; ++ }; ++ static thread_local CachedTime cached_time; ++ ++ const std::chrono::milliseconds epoch_time_ms = ++ std::chrono::duration_cast(system_time.time_since_epoch()); ++ ++ const std::chrono::seconds epoch_time_seconds = ++ std::chrono::duration_cast(epoch_time_ms); ++ ++ if (cached_time.formatted_time.empty() || cached_time.epoch_time_seconds != epoch_time_seconds) { ++ cached_time.formatted_time = ++ absl::FormatTime(DefaultDateFormat, absl::FromChrono(system_time), time_zone); ++ cached_time.epoch_time_seconds = epoch_time_seconds; ++ } else { ++ // Overwrite the digits in the ".000Z" at the end of the string with the ++ // millisecond count from the input time. ++ ASSERT(cached_time.formatted_time.length() == 24); ++ size_t offset = cached_time.formatted_time.length() - 4; ++ uint32_t msec = epoch_time_ms.count() % 1000; ++ cached_time.formatted_time[offset++] = ('0' + (msec / 100)); ++ msec %= 100; ++ cached_time.formatted_time[offset++] = ('0' + (msec / 10)); ++ msec %= 10; ++ cached_time.formatted_time[offset++] = ('0' + msec); ++ } ++ ++ return cached_time.formatted_time; ++} ++ ++} // namespace Formatter ++} // namespace Envoy +diff --git a/contrib/common/localtime_formatter/source/substitution_formatter.h b/contrib/common/localtime_formatter/source/substitution_formatter.h +new file mode 100644 +index 0000000000..7ba8535c19 +--- /dev/null ++++ b/contrib/common/localtime_formatter/source/substitution_formatter.h +@@ -0,0 +1,54 @@ ++#pragma once ++ ++#include ++#include ++#include ++ ++#include "envoy/common/time.h" ++#include "envoy/config/core/v3/base.pb.h" ++#include "envoy/formatter/substitution_formatter.h" ++#include "envoy/stream_info/stream_info.h" ++ ++#include "source/common/common/utility.h" ++ ++#include "absl/container/flat_hash_map.h" ++#include "absl/types/optional.h" ++ ++namespace Envoy { ++namespace Formatter { ++ ++/** ++ * Access log format parser. ++ */ ++class LocalStartTimeFormatter : public FormatterProvider { ++public: ++ LocalStartTimeFormatter(const std::string& format); ++ ++ // FormatterProvider ++ absl::optional format(const Http::RequestHeaderMap&, const Http::ResponseHeaderMap&, ++ const Http::ResponseTrailerMap&, const StreamInfo::StreamInfo&, ++ absl::string_view) const override; ++ ProtobufWkt::Value formatValue(const Http::RequestHeaderMap&, const Http::ResponseHeaderMap&, ++ const Http::ResponseTrailerMap&, const StreamInfo::StreamInfo&, ++ absl::string_view) const override; ++ ++ /** ++ * Utility class for access log date/time format with milliseconds support. ++ */ ++ class DateTimeFormatter { ++ public: ++ static std::string fromTime(const SystemTime& time, absl::TimeZone time_zone); ++ }; ++ ++ std::string parseFormat(const std::string& token, size_t parameters_start) { ++ const size_t parameters_length = token.length() - (parameters_start + 1); ++ return token[parameters_start - 1] == '(' ? token.substr(parameters_start, parameters_length) ++ : ""; ++ } ++ ++private: ++ const DateFormatter date_formatter_; ++}; ++ ++} // namespace Formatter ++} // namespace Envoy +diff --git a/contrib/common/localtime_formatter/test/BUILD b/contrib/common/localtime_formatter/test/BUILD +new file mode 100644 +index 0000000000..22f9658bdb +--- /dev/null ++++ b/contrib/common/localtime_formatter/test/BUILD +@@ -0,0 +1,29 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_test", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_test( ++ name = "substitution_formatter_test", ++ srcs = ["substitution_formatter_test.cc"], ++ deps = [ ++ "//contrib/common/localtime_formatter/source:substitution_formatter_lib", ++ "//source/common/common:utility_lib", ++ "//source/common/http:header_map_lib", ++ "//source/common/json:json_loader_lib", ++ "//source/common/network:address_lib", ++ "//source/common/router:string_accessor_lib", ++ "//test/mocks/api:api_mocks", ++ "//test/mocks/http:http_mocks", ++ "//test/mocks/ssl:ssl_mocks", ++ "//test/mocks/stream_info:stream_info_mocks", ++ "//test/test_common:threadsafe_singleton_injector_lib", ++ "//test/test_common:utility_lib", ++ "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/common/localtime_formatter/test/substitution_formatter_test.cc b/contrib/common/localtime_formatter/test/substitution_formatter_test.cc +new file mode 100644 +index 0000000000..8d92aaf5f4 +--- /dev/null ++++ b/contrib/common/localtime_formatter/test/substitution_formatter_test.cc +@@ -0,0 +1,68 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "envoy/config/core/v3/base.pb.h" ++#include "envoy/event/timer.h" ++ ++#include "source/common/common/logger.h" ++#include "source/common/common/utility.h" ++#include "source/common/formatter/substitution_formatter.h" ++#include "source/common/http/header_map_impl.h" ++#include "source/common/json/json_loader.h" ++#include "source/common/network/address_impl.h" ++#include "source/common/protobuf/utility.h" ++#include "source/common/router/string_accessor_impl.h" ++ ++#include "test/mocks/api/mocks.h" ++#include "test/mocks/http/mocks.h" ++#include "test/mocks/ssl/mocks.h" ++#include "test/mocks/stream_info/mocks.h" ++#include "test/test_common/printers.h" ++#include "test/test_common/threadsafe_singleton_injector.h" ++#include "test/test_common/utility.h" ++ ++#include "contrib/common/localtime_formatter/source/substitution_formatter.h" ++#include "gmock/gmock.h" ++#include "gtest/gtest.h" ++ ++using testing::NiceMock; ++using testing::Return; ++ ++namespace Envoy { ++namespace Formatter { ++namespace { ++ ++TEST(AlimeshSubstitutionFormatterTest, localStartTimeFormatter) { ++ NiceMock stream_info; ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, {":path", "/"}}; ++ Http::TestResponseHeaderMapImpl response_headers; ++ Http::TestResponseTrailerMapImpl response_trailers; ++ std::string body; ++ ++ { ++ LocalStartTimeFormatter local_start_time_format(""); ++ int rand = std::rand(); ++ std::shared_ptr time = ++ std::make_shared(Envoy::Event::TimeSystem::Microseconds(rand)); ++ EXPECT_CALL(stream_info, startTime()).WillRepeatedly(Return(*time)); ++ EXPECT_EQ(LocalStartTimeFormatter::DateTimeFormatter::fromTime(*time, absl::LocalTimeZone()), ++ local_start_time_format.format(request_headers, response_headers, response_trailers, ++ stream_info, body)); ++ } ++ ++ { ++ absl::Time abslStartTime = ++ TestUtility::parseTime("Dec 18 01:50:34 2018 GMT", "%b %e %H:%M:%S %Y GMT"); ++ SystemTime startTime = absl::ToChronoTime(abslStartTime); ++ ++ EXPECT_EQ("2018-12-18T01:50:34.000Z", LocalStartTimeFormatter::DateTimeFormatter::fromTime( ++ startTime, absl::LocalTimeZone())); ++ } ++} ++ ++} // namespace ++} // namespace Formatter ++} // namespace Envoy +diff --git a/contrib/contrib_build_config.bzl b/contrib/contrib_build_config.bzl +index 3a9987a910..ff403d915e 100644 +--- a/contrib/contrib_build_config.bzl ++++ b/contrib/contrib_build_config.bzl +@@ -4,9 +4,16 @@ CONTRIB_EXTENSIONS = { + # HTTP filters + # + ++ "envoy.filters.http.http_dubbo_transcoder": "//contrib/http_dubbo_transcoder/filters/http/source:config", + "envoy.filters.http.squash": "//contrib/squash/filters/http/source:config", + "envoy.filters.http.sxg": "//contrib/sxg/filters/http/source:config", + ++ # ++ # Upstreams ++ # ++ ++ "envoy.upstreams.http.dubbo_tcp": "//contrib/upstreams/http/dubbo_tcp/source:config", ++ + # + # Network filters + # +@@ -29,4 +36,10 @@ CONTRIB_EXTENSIONS = { + # + + "envoy.tls.key_providers.cryptomb": "//contrib/cryptomb/private_key_providers/source:config", ++ ++ # ++ # Custom cluster plugins ++ # ++ ++ "envoy.router.cluster_specifier_plugin.cluster_fallback": "//contrib/custom_cluster_plugins/cluster_fallback/source:config", + } +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/source/BUILD b/contrib/custom_cluster_plugins/cluster_fallback/source/BUILD +new file mode 100644 +index 0000000000..a9ddb6edf3 +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/source/BUILD +@@ -0,0 +1,39 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_contrib_extension", ++ "envoy_cc_library", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_library( ++ name = "filter_lib", ++ srcs = [ ++ "filter.cc", ++ ], ++ hdrs = [ ++ "filter.h", ++ ], ++ repository = "@envoy", ++ deps = [ ++ "//envoy/router:cluster_specifier_plugin_interface", ++ "//source/common/router:config_lib", ++ "@envoy_api//contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3:pkg_cc_proto", ++ ], ++) ++ ++envoy_cc_contrib_extension( ++ name = "config", ++ srcs = ["config.cc"], ++ hdrs = ["config.h"], ++ repository = "@envoy", ++ deps = [ ++ ":filter_lib", ++ "//source/extensions/filters/network:well_known_names", ++ "//source/extensions/filters/network/common:factory_base_lib", ++ "@envoy_api//contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/source/config.cc b/contrib/custom_cluster_plugins/cluster_fallback/source/config.cc +new file mode 100644 +index 0000000000..fe5158eeb6 +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/source/config.cc +@@ -0,0 +1,26 @@ ++#include "contrib/custom_cluster_plugins/cluster_fallback/source/config.h" ++ ++#include "contrib/custom_cluster_plugins/cluster_fallback/source/filter.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace CustomClusterPlugins { ++namespace ClusterFallback { ++ ++Envoy::Router::ClusterSpecifierPluginSharedPtr ++ClusterFallbackPluginFactoryConfig::createClusterSpecifierPlugin( ++ const Protobuf::Message& config, Server::Configuration::CommonFactoryContext& context) { ++ const auto& proto_config = ++ MessageUtil::downcastAndValidate( ++ config, context.messageValidationVisitor()); ++ return std::make_shared(proto_config, context); ++} ++ ++REGISTER_FACTORY(ClusterFallbackPluginFactoryConfig, ++ Envoy::Router::ClusterSpecifierPluginFactoryConfig); ++ ++} // namespace ClusterFallback ++} // namespace CustomClusterPlugins ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/source/config.h b/contrib/custom_cluster_plugins/cluster_fallback/source/config.h +new file mode 100644 +index 0000000000..d05294c585 +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/source/config.h +@@ -0,0 +1,37 @@ ++#pragma once ++ ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.h" ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.validate.h" ++ ++#include "envoy/router/cluster_specifier_plugin.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace CustomClusterPlugins { ++namespace ClusterFallback { ++ ++class ClusterFallbackPluginFactoryConfig ++ : public Envoy::Router::ClusterSpecifierPluginFactoryConfig { ++public: ++ ClusterFallbackPluginFactoryConfig() = default; ++ ++ std::string name() const override { ++ return "envoy.router.cluster_specifier_plugin.cluster_fallback"; ++ } ++ ++ Envoy::Router::ClusterSpecifierPluginSharedPtr ++ createClusterSpecifierPlugin(const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext& context) override; ++ ++ ProtobufTypes::MessagePtr createEmptyConfigProto() override { ++ return std::make_unique< ++ envoy::extensions::custom_cluster_plugins::cluster_fallback::v3::ClusterFallbackConfig>(); ++ } ++}; ++ ++DECLARE_FACTORY(ClusterFallbackPluginFactoryConfig); ++ ++} // namespace ClusterFallback ++} // namespace CustomClusterPlugins ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/source/filter.cc b/contrib/custom_cluster_plugins/cluster_fallback/source/filter.cc +new file mode 100644 +index 0000000000..f009b6318e +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/source/filter.cc +@@ -0,0 +1,118 @@ ++#include "contrib/custom_cluster_plugins/cluster_fallback/source/filter.h" ++ ++#include "source/common/common/assert.h" ++ ++#include "source/common/router/config_impl.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace CustomClusterPlugins { ++namespace ClusterFallback { ++ ++ClusterFallbackPlugin::ClusterFallbackPlugin( ++ const envoy::extensions::custom_cluster_plugins::cluster_fallback::v3::ClusterFallbackConfig& ++ config, ++ Server::Configuration::CommonFactoryContext& context) ++ : cluster_manager_(context.clusterManager()) { ++ if (config.config_specifier_case() == ++ envoy::extensions::custom_cluster_plugins::cluster_fallback::v3::ClusterFallbackConfig:: ++ kWeightedClusterConfig) { ++ for (auto& item : config.weighted_cluster_config().config()) { ++ clusters_config_.emplace(item.routing_cluster(), ++ std::vector(item.fallback_clusters().begin(), ++ item.fallback_clusters().end())); ++ } ++ } else { ++ clusters_config_.emplace( ++ config.cluster_config().routing_cluster(), ++ std::vector(config.cluster_config().fallback_clusters().begin(), ++ config.cluster_config().fallback_clusters().end())); ++ } ++ ++ if (clusters_config_.empty()) { ++ ENVOY_LOG(info, "there is no fallback cluster"); ++ } ++} ++ ++Envoy::Router::RouteConstSharedPtr ++ClusterFallbackPlugin::route(const Envoy::Router::RouteEntry& route_entry, ++ const Http::RequestHeaderMap&) const { ++ if (typeid(route_entry) == typeid(Envoy::Router::RouteEntryImplBase::WeightedClusterEntry&) || ++ typeid(route_entry) == typeid(Envoy::Router::RouteEntryImplBase::DynamicRouteEntry&)) { ++ return calculateWeightedClusterFallback(route_entry); ++ } ++ ++ ASSERT(dynamic_cast(&route_entry) != nullptr); ++ return calculateNormalClusterFallback(route_entry); ++} ++ ++Envoy::Router::RouteConstSharedPtr ClusterFallbackPlugin::calculateNormalClusterFallback( ++ const Envoy::Router::RouteEntry& route_entry) const { ++ ASSERT(clusters_config_.size() == 1); ++ ++ const auto& base = dynamic_cast(route_entry); ++ auto first_item = clusters_config_.begin(); ++ if (hasHealthHost(first_item->first)) { ++ ENVOY_LOG(info, "The target cluster {} has healthy nodes and does not require fallback", ++ first_item->first); ++ return base.clone(first_item->first); ++ } ++ ++ for (const auto& cluster_name : first_item->second) { ++ if (hasHealthHost(cluster_name)) { ++ return base.clone(cluster_name); ++ } ++ } ++ ++ ENVOY_LOG(info, "All clusters have no healthy nodes, the original routing cluster is returned"); ++ return base.clone(first_item->first); ++} ++ ++Envoy::Router::RouteConstSharedPtr ClusterFallbackPlugin::calculateWeightedClusterFallback( ++ const Envoy::Router::RouteEntry& route_entry) const { ++ const auto& cluster_entry = ++ dynamic_cast(route_entry); ++ ++ auto search = clusters_config_.find(route_entry.clusterName()); ++ if (search == clusters_config_.end()) { ++ ENVOY_LOG(warn, "there is no fallback cluster config, the original routing cluster is returned"); ++ return cluster_entry.getRouteConstSharedPtr(); ++ } ++ ++ if (hasHealthHost(search->first)) { ++ ENVOY_LOG(info, "The target cluster {} has healthy nodes and does not require fallback", ++ search->first); ++ return cluster_entry.getRouteConstSharedPtr(); ++ } ++ ++ for (const auto& cluster_name : search->second) { ++ if (hasHealthHost(cluster_name)) { ++ return cluster_entry.clone(cluster_name); ++ } ++ } ++ ++ ENVOY_LOG(info, "All clusters have no healthy nodes, the original routing cluster is returned"); ++ return cluster_entry.getRouteConstSharedPtr(); ++} ++ ++bool ClusterFallbackPlugin::hasHealthHost(absl::string_view cluster_name) const { ++ bool has_health_host{false}; ++ Upstream::ThreadLocalCluster* cluster = cluster_manager_.getThreadLocalCluster(cluster_name); ++ if (!cluster) { ++ return has_health_host; ++ } ++ ++ for (auto& i : cluster->prioritySet().hostSetsPerPriority()) { ++ if (i->healthyHosts().size() > 0) { ++ has_health_host = true; ++ break; ++ } ++ } ++ ++ return has_health_host; ++} ++ ++} // namespace ClusterFallback ++} // namespace CustomClusterPlugins ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/source/filter.h b/contrib/custom_cluster_plugins/cluster_fallback/source/filter.h +new file mode 100644 +index 0000000000..d11ce9ca33 +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/source/filter.h +@@ -0,0 +1,45 @@ ++#pragma once ++ ++#include ++#include ++ ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.h" ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.validate.h" ++ ++#include "envoy/router/cluster_specifier_plugin.h" ++#include "envoy/upstream/cluster_manager.h" ++ ++#include "source/common/common/logger_impl.h" ++#include "source/common/common/logger.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace CustomClusterPlugins { ++namespace ClusterFallback { ++ ++class ClusterFallbackPlugin : public Envoy::Router::ClusterSpecifierPlugin, ++ public Logger::Loggable { ++public: ++ ClusterFallbackPlugin( ++ const envoy::extensions::custom_cluster_plugins::cluster_fallback::v3::ClusterFallbackConfig& ++ config, ++ Server::Configuration::CommonFactoryContext& context); ++ ++ Envoy::Router::RouteConstSharedPtr route(const Envoy::Router::RouteEntry& parent, ++ const Http::RequestHeaderMap&) const; ++ ++private: ++ bool hasHealthHost(absl::string_view cluster_name) const; ++ Envoy::Router::RouteConstSharedPtr ++ calculateWeightedClusterFallback(const Envoy::Router::RouteEntry& route_entry) const; ++ Envoy::Router::RouteConstSharedPtr ++ calculateNormalClusterFallback(const Envoy::Router::RouteEntry& route_entry) const; ++ ++ Upstream::ClusterManager& cluster_manager_; ++ std::unordered_map/*fallback clusters*/> clusters_config_; ++}; ++ ++} // namespace ClusterFallback ++} // namespace CustomClusterPlugins ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/test/BUILD b/contrib/custom_cluster_plugins/cluster_fallback/test/BUILD +new file mode 100644 +index 0000000000..81c939afd6 +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/test/BUILD +@@ -0,0 +1,37 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_test", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_test( ++ name = "config_test", ++ srcs = ["config_test.cc"], ++ deps = [ ++ "//contrib/custom_cluster_plugins/cluster_fallback/source:config", ++ "//test/mocks/server:factory_context_mocks", ++ "//test/test_common:utility_lib", ++ "@envoy_api//contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3:pkg_cc_proto", ++ ], ++) ++ ++envoy_cc_test( ++ name = "filter_test", ++ srcs = ["filter_test.cc"], ++ deps = [ ++ "//contrib/custom_cluster_plugins/cluster_fallback/source:config", ++ "//contrib/custom_cluster_plugins/cluster_fallback/source:filter_lib", ++ "//test/mocks/server:factory_context_mocks", ++ "//test/mocks/upstream:cluster_manager_mocks", ++ "//test/mocks/upstream:cluster_mocks", ++ "//test/mocks/upstream:host_mocks", ++ "//test/mocks/upstream:host_set_mocks", ++ "//test/mocks/upstream:thread_local_cluster_mocks", ++ "//test/test_common:utility_lib", ++ "@envoy_api//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg_cc_proto", ++ ], ++) +\ No newline at end of file +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/test/config_test.cc b/contrib/custom_cluster_plugins/cluster_fallback/test/config_test.cc +new file mode 100644 +index 0000000000..c68e13229d +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/test/config_test.cc +@@ -0,0 +1,48 @@ ++#include "test/mocks/server/factory_context.h" ++#include "test/test_common/utility.h" ++ ++#include "contrib/custom_cluster_plugins/cluster_fallback/source/config.h" ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.h" ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.validate.h" ++ ++#include "gmock/gmock.h" ++#include "gtest/gtest.h" ++ ++using testing::_; ++ ++namespace Envoy { ++namespace Extensions { ++namespace CustomClusterPlugins { ++namespace ClusterFallback { ++ ++TEST(ClusterFallbackPluginFactoryConfigTest, ClusterFallbackPluginCorrectYaml) { ++ const std::string yaml_string = R"EOF( ++extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - fallback2 ++)EOF"; ++ ++ envoy::config::route::v3::ClusterSpecifierPlugin plugin_config; ++ TestUtility::loadFromYaml(yaml_string, plugin_config); ++ ++ auto* factory = ++ Envoy::Config::Utility::getFactory( ++ plugin_config.extension()); ++ EXPECT_NE(nullptr, factory); ++ ++ auto config = Envoy::Config::Utility::translateToFactoryConfig( ++ plugin_config.extension(), ProtobufMessage::getStrictValidationVisitor(), *factory); ++ NiceMock context; ++ auto plugin = factory->createClusterSpecifierPlugin(*config, context); ++ EXPECT_NE(nullptr, plugin); ++} ++ ++} // namespace ClusterFallback ++} // namespace CustomClusterPlugins ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/custom_cluster_plugins/cluster_fallback/test/filter_test.cc b/contrib/custom_cluster_plugins/cluster_fallback/test/filter_test.cc +new file mode 100644 +index 0000000000..84bbc015d5 +--- /dev/null ++++ b/contrib/custom_cluster_plugins/cluster_fallback/test/filter_test.cc +@@ -0,0 +1,686 @@ ++#include "contrib/custom_cluster_plugins/cluster_fallback/source/filter.h" ++ ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.h" ++#include "contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.validate.h" ++#include "contrib/custom_cluster_plugins/cluster_fallback/source/config.h" ++#include "source/common/router/config_impl.h" ++ ++#include "test/mocks/server/instance.h" ++#include "test/mocks/router/mocks.h" ++#include "test/mocks/upstream/cluster_manager.h" ++#include "test/mocks/upstream/host.h" ++#include "test/mocks/upstream/priority_set.h" ++ ++#include "gmock/gmock.h" ++#include "gtest/gtest.h" ++ ++using testing::_; ++using testing::ReturnRef; ++ ++namespace Envoy { ++namespace Extensions { ++namespace CustomClusterPlugins { ++namespace ClusterFallback { ++ ++Http::TestRequestHeaderMapImpl genHeaders(const std::string& host, const std::string& path, ++ const std::string& method, const std::string& scheme) { ++ auto hdrs = ++ Http::TestRequestHeaderMapImpl{{":authority", host}, {":path", path}, ++ {":method", method}, {"x-safe", "safe"}, ++ {"x-global-nope", "global"}, {"x-vhost-nope", "vhost"}, ++ {"x-route-nope", "route"}, {":scheme", scheme}, ++ {"x-forwarded-proto", scheme}}; ++ ++ if (scheme.empty()) { ++ hdrs.remove(":scheme"); ++ } ++ ++ return hdrs; ++} ++ ++Http::TestRequestHeaderMapImpl genHeaders(const std::string& host, const std::string& path, ++ const std::string& method) { ++ return genHeaders(host, path, method, "http"); ++} ++ ++TEST(ClusterFallbackPluginTest, NormalWithInlinePlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ cluster_config: ++ routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - fallback2 ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock factory_context; ++ NiceMock stream_info; ++ ++ std::shared_ptr test_cluster = ++ std::make_shared>(); ++ auto mock_host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{mock_host}; ++ Envoy::Upstream::MockHostSet* mock_host_set = ++ test_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*mock_host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(test_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ auto route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("test", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, OnceFallbackWithInlinePlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ cluster_config: ++ routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - fallback2 ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock factory_context; ++ NiceMock stream_info; ++ ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(nullptr)); ++ ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ auto host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{host}; ++ Envoy::Upstream::MockHostSet* mock_host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*mock_host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .WillOnce(Return(fallback1_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ auto route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("fallback1", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, TwiceFallbackWithInlinePlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ cluster_config: ++ routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - fallback2 ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock factory_context; ++ ++ // cluster test does not exist. ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(nullptr)); ++ ++ // cluster fallback1 is empty. ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ Envoy::Upstream::MockHostSet* mock_host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ Envoy::Upstream::HostVector empty_hosts{}; ++ EXPECT_CALL(*mock_host_set, healthyHosts()).WillOnce(ReturnRef(empty_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .WillOnce(Return(fallback1_cluster.get())); ++ ++ std::shared_ptr fallback2_cluster = ++ std::make_shared>(); ++ auto host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{host}; ++ Envoy::Upstream::MockHostSet* host_set = ++ fallback2_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback2"))) ++ .WillOnce(Return(fallback2_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ NiceMock stream_info; ++ auto route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("fallback2", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, NoHealthClusterWithInlinePlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/bar" ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ cluster_config: ++ routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ )EOF"; ++ ++ NiceMock factory_context; ++ ++ // cluster test is empty. ++ std::shared_ptr test_cluster = ++ std::make_shared>(); ++ Envoy::Upstream::MockHostSet* mock_host_set_test = ++ test_cluster->cluster_.prioritySet().getMockHostSet(0); ++ Envoy::Upstream::HostVector empty_hosts_test{}; ++ EXPECT_CALL(*mock_host_set_test, healthyHosts()).WillOnce(ReturnRef(empty_hosts_test)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(test_cluster.get())); ++ ++ // cluster fallback1 is empty. ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ Envoy::Upstream::MockHostSet* mock_host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ Envoy::Upstream::HostVector empty_hosts{}; ++ EXPECT_CALL(*mock_host_set, healthyHosts()).WillOnce(ReturnRef(empty_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .WillOnce(Return(fallback1_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ NiceMock stream_info; ++ auto route = config.route(genHeaders("some_cluster", "/bar", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("test", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, ClusterSpecifierPlugin) { ++ const std::string yaml = R"EOF( ++cluster_specifier_plugins: ++- extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ cluster_config: ++ routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - fallback2 ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ )EOF"; ++ ++ NiceMock factory_context; ++ ++ // cluster test is empty. ++ std::shared_ptr test_cluster = ++ std::make_shared>(); ++ Envoy::Upstream::MockHostSet* mock_host_set_test = ++ test_cluster->cluster_.prioritySet().getMockHostSet(0); ++ Envoy::Upstream::HostVector empty_hosts_test{}; ++ EXPECT_CALL(*mock_host_set_test, healthyHosts()).Times(2).WillRepeatedly(ReturnRef(empty_hosts_test)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .Times(2).WillRepeatedly(Return(test_cluster.get())); ++ ++ // cluster fallback1 is empty. ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ Envoy::Upstream::MockHostSet* mock_host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ Envoy::Upstream::HostVector empty_hosts{}; ++ EXPECT_CALL(*mock_host_set, healthyHosts()).Times(2).WillRepeatedly(ReturnRef(empty_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .Times(2).WillRepeatedly(Return(fallback1_cluster.get())); ++ ++ std::shared_ptr fallback2_cluster = ++ std::make_shared>(); ++ auto host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{host}; ++ Envoy::Upstream::MockHostSet* host_set = ++ fallback2_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*host_set, healthyHosts()).Times(2).WillRepeatedly(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback2"))) ++ .Times(2).WillRepeatedly(Return(fallback2_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ NiceMock stream_info; ++ auto route = config.route(genHeaders("some_cluster", "/bar", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("fallback2", route->routeEntry()->clusterName()); ++ ++ route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("fallback2", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, WeightedClusterNormalWithInlinePlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: test ++ weight: 100 ++ - name: cluster2 ++ weight: 0 ++ inline_cluster_specifier_plugin: ++ extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ weighted_cluster_config: ++ config: ++ - routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - routing_cluster: cluster2 ++ fallback_clusters: ++ - fallback2 ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock factory_context; ++ NiceMock stream_info; ++ ++ std::shared_ptr test_cluster = ++ std::make_shared>(); ++ auto mock_host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{mock_host}; ++ Envoy::Upstream::MockHostSet* mock_host_set = ++ test_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*mock_host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(test_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ auto route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("test", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, WeightedClusterFallbackWithInlinePlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: test ++ weight: 100 ++ - name: cluster2 ++ weight: 0 ++ inline_cluster_specifier_plugin: ++ extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ weighted_cluster_config: ++ config: ++ - routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - routing_cluster: cluster2 ++ fallback_clusters: ++ - fallback2 ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock factory_context; ++ NiceMock stream_info; ++ ++ // cluster test does not exist. ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(nullptr)); ++ ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ auto mock_host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{mock_host}; ++ Envoy::Upstream::MockHostSet* host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .WillOnce(Return(fallback1_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ auto route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("fallback1", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, WeightedClusterFallback) { ++ const std::string yaml = R"EOF( ++cluster_specifier_plugins: ++- extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ weighted_cluster_config: ++ config: ++ - routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - routing_cluster: cluster2 ++ fallback_clusters: ++ - fallback2 ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: test ++ weight: 100 ++ - name: cluster2 ++ weight: 0 ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ )EOF"; ++ ++ NiceMock factory_context; ++ NiceMock stream_info; ++ ++ // cluster test does not exist. ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(nullptr)); ++ ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ auto mock_host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{mock_host}; ++ Envoy::Upstream::MockHostSet* host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .WillOnce(Return(fallback1_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ auto route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("fallback1", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, WeightedClusterNoHealthHost) { ++ const std::string yaml = R"EOF( ++cluster_specifier_plugins: ++- extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ weighted_cluster_config: ++ config: ++ - routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - routing_cluster: cluster2 ++ fallback_clusters: ++ - fallback2 ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: test ++ weight: 100 ++ - name: cluster2 ++ weight: 0 ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ )EOF"; ++ ++ NiceMock factory_context; ++ NiceMock stream_info; ++ ++ // cluster test does not exist. ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(nullptr)); ++ ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts; ++ Envoy::Upstream::MockHostSet* host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .WillOnce(Return(fallback1_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ auto route = config.route(genHeaders("some_cluster", "/foo", "GET"), stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("test", route->routeEntry()->clusterName()); ++} ++ ++TEST(ClusterFallbackPluginTest, WeightedClusterFallbackViaClusterHeader) { ++ const std::string yaml = R"EOF( ++cluster_specifier_plugins: ++- extension: ++ name: envoy.router.cluster_specifier_plugin.cluster_fallback ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ weighted_cluster_config: ++ config: ++ - routing_cluster: test ++ fallback_clusters: ++ - fallback1 ++ - routing_cluster: cluster2 ++ fallback_clusters: ++ - fallback2 ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ weighted_clusters: ++ clusters: ++ - cluster_header: cluster ++ weight: 100 ++ - name: cluster2 ++ weight: 0 ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_specifier_plugin: envoy.router.cluster_specifier_plugin.cluster_fallback ++ )EOF"; ++ ++ NiceMock factory_context; ++ NiceMock stream_info; ++ ++ // cluster test does not exist. ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("test"))) ++ .WillOnce(Return(nullptr)); ++ ++ std::shared_ptr fallback1_cluster = ++ std::make_shared>(); ++ auto mock_host = std::make_shared>(); ++ Envoy::Upstream::HostVector mock_hosts{mock_host}; ++ Envoy::Upstream::MockHostSet* host_set = ++ fallback1_cluster->cluster_.prioritySet().getMockHostSet(0); ++ EXPECT_CALL(*host_set, healthyHosts()).WillOnce(ReturnRef(mock_hosts)); ++ EXPECT_CALL(factory_context.cluster_manager_, getThreadLocalCluster(testing::Eq("fallback1"))) ++ .WillOnce(Return(fallback1_cluster.get())); ++ ++ envoy::config::route::v3::RouteConfiguration route_config; ++ TestUtility::loadFromYaml(yaml, route_config); ++ ++ const Envoy::Router::OptionalHttpFilters& optional_http_filters = ++ Envoy::Router::OptionalHttpFilters(); ++ Envoy::Router::ConfigImpl config(route_config, optional_http_filters, factory_context, ++ ProtobufMessage::getNullValidationVisitor(), false); ++ ++ Http::TestRequestHeaderMapImpl header = genHeaders("some_cluster", "/foo", "GET"); ++ header.setByKey("cluster", "test"); ++ auto route = config.route(header, stream_info, 0); ++ EXPECT_NE(nullptr, route); ++ EXPECT_EQ("fallback1", route->routeEntry()->clusterName()); ++} ++ ++} // namespace ClusterFallback ++} // namespace CustomClusterPlugins ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/envoy/http/BUILD b/contrib/envoy/http/BUILD +new file mode 100644 +index 0000000000..b20612de58 +--- /dev/null ++++ b/contrib/envoy/http/BUILD +@@ -0,0 +1,23 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_library", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_library( ++ name = "active_redirect_policy_interface", ++ hdrs = ["active_redirect_policy.h"], ++ visibility = ["//visibility:public"], ++ deps = [ ++ "//envoy/http:codes_interface", ++ "//envoy/http:header_map_interface", ++ "//envoy/router:internal_redirect_interface", ++ "//envoy/stream_info:stream_info_interface", ++ "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ++ "@envoy_api//envoy/config/route/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/envoy/http/active_redirect_policy.h b/contrib/envoy/http/active_redirect_policy.h +new file mode 100644 +index 0000000000..7ed5ded7fe +--- /dev/null ++++ b/contrib/envoy/http/active_redirect_policy.h +@@ -0,0 +1,66 @@ ++#pragma once ++ ++#include ++#include ++ ++#include "envoy/config/core/v3/base.pb.h" ++#include "envoy/config/route/v3/route_components.pb.h" ++#include "envoy/http/codes.h" ++#include "envoy/http/header_map.h" ++#include "envoy/router/internal_redirect.h" ++#include "envoy/stream_info/stream_info.h" ++ ++namespace Envoy { ++ ++namespace Router { ++ ++/** ++ * InternalActiveRedirectPolicy from the route configuration. ++ */ ++class InternalActiveRedirectPolicy { ++public: ++ virtual ~InternalActiveRedirectPolicy() = default; ++ ++ /** ++ * @return whether internal redirect is enabled on this route. ++ */ ++ virtual bool enabled() const PURE; ++ ++ /** ++ * @param response_code the response code from the upstream. ++ * @return whether the given response_code should trigger an internal redirect on this route. ++ */ ++ virtual bool shouldRedirectForResponseCode(const Http::Code& response_code) const PURE; ++ ++ /** ++ * Creates the target route predicates. This should really be called only once for each upstream ++ * redirect response. Creating the predicates lazily to avoid wasting CPU cycles on non-redirect ++ * responses, which should be the most common case. ++ * @return a vector of newly constructed InternalRedirectPredicate instances. ++ */ ++ virtual std::vector predicates() const PURE; ++ ++ /** ++ * @return the maximum number of allowed internal redirects on this route. ++ */ ++ virtual uint32_t maxInternalRedirects() const PURE; ++ ++ /** ++ * @return if it is allowed to follow the redirect with a different scheme in ++ * the target URI than the downstream request. ++ */ ++ virtual bool isCrossSchemeRedirectAllowed() const PURE; ++ ++ virtual void evaluateHeaders(Http::HeaderMap& headers, ++ const StreamInfo::StreamInfo* stream_info) const PURE; ++ ++ virtual std::string ++ redirectUrl(absl::optional current_path = absl::nullopt) const PURE; ++ ++ virtual bool forcedUseOriginalHost() const PURE; ++ ++ virtual bool forcedAddHeaderBeforeRouteMatcher() const PURE; ++}; ++ ++} // namespace Router ++} // namespace Envoy +diff --git a/contrib/extensions_metadata.yaml b/contrib/extensions_metadata.yaml +index 215a7936f0..6d42f83f38 100644 +--- a/contrib/extensions_metadata.yaml ++++ b/contrib/extensions_metadata.yaml +@@ -1,3 +1,13 @@ ++envoy.filters.http.http_dubbo_transcoder: ++ categories: ++ - envoy.filters.http ++ security_posture: requires_trusted_downstream_and_upstream ++ status: stable ++envoy.upstreams.http.dubbo_tcp: ++ categories: ++ - envoy.upstreams ++ security_posture: robust_to_untrusted_downstream ++ status: stable + envoy.filters.http.squash: + categories: + - envoy.filters.http +@@ -48,3 +58,8 @@ envoy.tls.key_providers.cryptomb: + - envoy.tls.key_providers + security_posture: robust_to_untrusted_downstream + status: alpha ++envoy.router.cluster_specifier_plugin.cluster_fallback: ++ categories: ++ - envoy.router ++ security_posture: robust_to_untrusted_downstream ++ status: alpha +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/BUILD b/contrib/http_dubbo_transcoder/filters/http/source/BUILD +new file mode 100644 +index 0000000000..90cbab579f +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/BUILD +@@ -0,0 +1,90 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_contrib_extension", ++ "envoy_cc_library", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_library( ++ name = "dubbo_transcoder_filter_lib", ++ srcs = ["dubbo_transcoder_filter.cc"], ++ hdrs = ["dubbo_transcoder_filter.h"], ++ external_deps = [ ++ "path_matcher", ++ "hessian2_codec_codec_impl", ++ "hessian2_codec_object_codec_lib", ++ ], ++ visibility = ["//visibility:public"], ++ deps = [ ++ ":transcoder_interface", ++ ":utility_lib", ++ "//envoy/event:dispatcher_interface", ++ "//envoy/http:codes_interface", ++ "//envoy/http:filter_interface", ++ "//envoy/http:query_params_interface", ++ "//source/common/buffer:buffer_lib", ++ "//source/common/common:assert_lib", ++ "//source/common/common:enum_to_int", ++ "//source/common/common:minimal_logger_lib", ++ "//source/common/common:regex_lib", ++ "//source/common/http:codes_lib", ++ "//source/common/http:header_map_lib", ++ "//source/common/http:headers_lib", ++ "//source/common/http:utility_lib", ++ "//source/common/runtime:runtime_lib", ++ "//source/common/common:hex_lib", ++ "//source/extensions/filters/http:well_known_names", ++ "@com_google_googleapis//google/api:http_cc_proto", ++ "@envoy_api//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg_cc_proto", ++ "@envoy_api//envoy/type/matcher/v3:pkg_cc_proto", ++ ], ++) ++ ++envoy_cc_contrib_extension( ++ name = "config", ++ srcs = ["config.cc"], ++ hdrs = ["config.h"], ++ visibility = ["//visibility:public"], ++ deps = [ ++ ":dubbo_transcoder_filter_lib", ++ "//envoy/registry", ++ "//source/extensions/filters/http:well_known_names", ++ "//source/extensions/filters/http/common:factory_base_lib", ++ "@envoy_api//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg_cc_proto", ++ ], ++) ++ ++envoy_cc_library( ++ name = "transcoder_interface", ++ hdrs = ["transcoder.h"], ++ deps = [ ++ "//envoy/http:filter_interface", ++ "@envoy_api//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg_cc_proto", ++ ], ++) ++ ++envoy_cc_library( ++ name = "utility_lib", ++ srcs = ["utility.cc"], ++ hdrs = ["utility.h"], ++ external_deps = [ ++ "hessian2_codec_object_impl", ++ "hessian2_codec_codec_impl", ++ "hessian2_codec_object_codec_lib", ++ "json", ++ ], ++ deps = [ ++ ":transcoder_interface", ++ "//envoy/http:filter_interface", ++ "//envoy/http:query_params_interface", ++ "//source/common/buffer:buffer_lib", ++ "//source/common/common:enum_to_int", ++ "//source/common/http:codes_lib", ++ "//source/common/http:utility_lib", ++ "@envoy_api//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/config.cc b/contrib/http_dubbo_transcoder/filters/http/source/config.cc +new file mode 100644 +index 0000000000..81f9827cdc +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/config.cc +@@ -0,0 +1,32 @@ ++#include "contrib/http_dubbo_transcoder/filters/http/source/config.h" ++ ++#include "contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++Http::FilterFactoryCb HttpDubboTranscodeFilterFactory::createFilterFactoryFromProtoTyped( ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder& proto_config, ++ const std::string&, Server::Configuration::FactoryContext&) { ++ DubboTranscoderConfigSharedPtr config = std::make_shared(proto_config); ++ return [config](Http::FilterChainFactoryCallbacks& callbacks) -> void { ++ callbacks.addStreamFilter(std::make_shared(*config)); ++ }; ++} ++ ++Router::RouteSpecificFilterConfigConstSharedPtr ++HttpDubboTranscodeFilterFactory::createRouteSpecificFilterConfigTyped( ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder& proto_config, ++ Server::Configuration::ServerFactoryContext&, ProtobufMessage::ValidationVisitor&) { ++ return std::make_shared(proto_config); ++}; ++ ++REGISTER_FACTORY(HttpDubboTranscodeFilterFactory, ++ Server::Configuration::NamedHttpFilterConfigFactory); ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/config.h b/contrib/http_dubbo_transcoder/filters/http/source/config.h +new file mode 100644 +index 0000000000..80161be035 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/config.h +@@ -0,0 +1,41 @@ ++#pragma once ++ ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.h" ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.h" ++ ++#include "source/extensions/filters/http/common/factory_base.h" ++#include "source/extensions/filters/http/well_known_names.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++/** ++ * Config registration for the buffer filter. ++ */ ++class HttpDubboTranscodeFilterFactory ++ : public Common::FactoryBase< ++ envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder> { ++public: ++ HttpDubboTranscodeFilterFactory() : FactoryBase("envoy.filters.http.http_dubbo_transcoder") {} ++ ++private: ++ Http::FilterFactoryCb createFilterFactoryFromProtoTyped( ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder& ++ proto_config, ++ const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override; ++ ++ Router::RouteSpecificFilterConfigConstSharedPtr createRouteSpecificFilterConfigTyped( ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder& ++ proto_config, ++ Server::Configuration::ServerFactoryContext& context, ++ ProtobufMessage::ValidationVisitor& validator) override; ++}; ++ ++DECLARE_FACTORY(HttpDubboTranscodeFilterFactory); ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.cc b/contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.cc +new file mode 100644 +index 0000000000..0d8f0b6000 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.cc +@@ -0,0 +1,577 @@ ++#include "contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.h" ++ ++#include "source/common/common/assert.h" ++#include "source/common/common/hex.h" ++#include "source/common/common/regex.h" ++#include "source/common/http/status.h" ++#include "source/common/http/utility.h" ++#include "source/extensions/filters/http/well_known_names.h" ++ ++#include "absl/status/status.h" ++#include "absl/strings/str_split.h" ++ ++#include "contrib/http_dubbo_transcoder/filters/http/source/utility.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++static const std::string HTTPResponseKey = "result"; ++static const std::string HTTPResponseErrorKey = "error"; ++static const std::string HTTPResponseAttachmentKey = "attachment"; ++ ++static const std::string DubboGenericMethodName = "$invoke"; ++static const std::string DubboGenericParamTypes = ++ "Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;"; ++ ++static const std::string DubboDefaultProtocolVsersion = "2.7.1"; ++static const std::string DubboDefaultMethodVersion = "0.0.0"; ++ ++static const std::string AttachmentPathKey = "path"; ++static const std::string AttachmentGenericKey = "generic"; ++static const std::string AttachmentInterfaceKey = "interface"; ++static const std::string AttachmentVersionKey = "version"; ++static const std::string AttachmentTrueValue = "true"; ++static const std::string AttachmentGroupKey = "group"; ++constexpr uint8_t EVENT_BIT_ON = 0x20; ++static std::atomic_ulong RequestId{0}; ++ ++DubboTranscoderConfig::DubboTranscoderConfig( ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder& ++ proto_config) { ++ ++ disabled_ = proto_config.services_mapping().empty(); ++ if (disabled_) { ++ return; ++ } ++ ++ request_validate_options_ = proto_config.request_validation_options(); ++ ++ // build path matcher ++ ::google::grpc::transcoding::PathMatcherBuilder pmb; ++ for (const auto& service : proto_config.services_mapping()) { ++ for (const auto& method : service.method_mapping()) { ++ MethodInfoSharedPtr method_info = ++ createMethodInfo(service.name(), service.version(), service.group(), method); ++ pmb.Register(method_info->match_http_method_, method_info->match_pattern_, "", method_info); ++ } ++ } ++ switch (proto_config.url_unescape_spec()) { ++ case envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder:: ++ ALL_CHARACTERS_EXCEPT_RESERVED: ++ pmb.SetUrlUnescapeSpec( ++ google::grpc::transcoding::UrlUnescapeSpec::kAllCharactersExceptReserved); ++ break; ++ case envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder:: ++ ALL_CHARACTERS_EXCEPT_SLASH: ++ pmb.SetUrlUnescapeSpec(google::grpc::transcoding::UrlUnescapeSpec::kAllCharactersExceptSlash); ++ break; ++ case envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder:: ++ ALL_CHARACTERS: ++ pmb.SetUrlUnescapeSpec(google::grpc::transcoding::UrlUnescapeSpec::kAllCharacters); ++ break; ++ default: ++ NOT_REACHED_GCOVR_EXCL_LINE; ++ } ++ path_matcher_ = pmb.Build(); ++} ++ ++MethodInfoSharedPtr DubboTranscoderConfig::createMethodInfo( ++ const std::string& service_name, const std::string& service_version, ++ const std::string& service_group, ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder:: ++ DubboMethodMapping& method_mapping) { ++ MethodInfoSharedPtr method_info = std::make_shared(); ++ method_info->service_name_ = service_name; ++ method_info->service_version_ = service_version; ++ method_info->service_group_ = service_group; ++ method_info->name_ = method_mapping.name(); ++ ++ if (method_mapping.has_path_matcher()) { ++ std::string http_method_spec = envoy::extensions::filters::http::http_dubbo_transcoder::v3:: ++ HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec_Name( ++ method_mapping.path_matcher().match_http_method_spec()); ++ method_info->match_http_method_ = std::string(absl::StripPrefix(http_method_spec, "ALL_")); ++ method_info->match_pattern_ = method_mapping.path_matcher().match_pattern(); ++ } else { ++ // Default matching path: service/method, http method: get. ++ std::string http_method_spec = envoy::extensions::filters::http::http_dubbo_transcoder::v3:: ++ HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec_Name( ++ envoy::extensions::filters::http::http_dubbo_transcoder::v3:: ++ HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec_ALL_GET); ++ method_info->match_http_method_ = std::string(absl::StripPrefix(http_method_spec, "ALL_")); ++ method_info->match_pattern_ = fmt::format("/{}/{}", service_name, method_info->name_); ++ } ++ ++ ENVOY_LOG(debug, "http method: {}, match pattern {}", method_info->match_http_method_, ++ method_info->match_pattern_); ++ ++ if (!method_mapping.parameter_mapping().empty()) { ++ method_info->parameter_mapping_ = method_mapping.parameter_mapping(); ++ } ++ ++ if (method_mapping.has_passthrough_setting()) { ++ const auto& passthrough_setting = method_mapping.passthrough_setting(); ++ ++ using PassthroughSetting = envoy::extensions::filters::http::http_dubbo_transcoder::v3:: ++ HttpDubboTranscoder::DubboMethodMapping::PassthroughSetting; ++ switch (method_mapping.passthrough_setting().headers_setting_case()) { ++ case PassthroughSetting::kPassthroughAllHeaders: ++ method_info->passthrough_all_headers_ = passthrough_setting.passthrough_all_headers(); ++ break; ++ case PassthroughSetting::kPassthroughHeaders: ++ method_info->passthrough_header_keys_ = passthrough_setting.passthrough_headers().keys(); ++ break; ++ default: ++ NOT_REACHED_GCOVR_EXCL_LINE; ++ } ++ } ++ ++ return method_info; ++} ++ ++std::tuple ++DubboTranscoderConfig::createTranscoder(Http::RequestHeaderMap& headers) const { ++ ASSERT(!disabled_); ++ ++ const std::string method(headers.getMethodValue()); ++ std::string path(headers.getPathValue()); ++ std::string args; ++ ++ const size_t pos = path.find('?'); ++ if (pos != std::string::npos) { ++ args = path.substr(pos + 1); ++ path = path.substr(0, pos); ++ } ++ ++ ENVOY_LOG(debug, "path is {} args is {} method is {}", path, args, method); ++ ++ std::vector variable_bindings; ++ auto method_info = path_matcher_->Lookup(method, path, args, &variable_bindings, nullptr); ++ if (!method_info) { ++ return {absl::NotFoundError(fmt::format("Could not resolve {} to a method", path)), nullptr}; ++ } ++ ++ return {absl::OkStatus(), new Http2DubboTranscoder(*method_info, std::move(variable_bindings))}; ++} ++ ++Http2DubboTranscoder::Http2DubboTranscoder(const MethodInfo& method_info, ++ std::vector&& bindings) ++ : method_info_(method_info), bindings_(std::move(bindings)) { ++ ENVOY_LOG(debug, "method name is {} method args count is {}", method_info_.name_, ++ method_info_.parameter_mapping_.size()); ++}; ++ ++absl::Status Http2DubboTranscoder::translateDubboToHttp(Buffer::Instance& data) { ++ if (response_buffer_.length() == 0) { ++ response_buffer_.move(data); ++ ++ if (response_buffer_.length() < DUBBO_HEADER_SIZE) { ++ return absl::DataLossError("Dubbo message data is incomplete"); ++ } ++ ++ if (!validateMagicNumber(response_buffer_)) { ++ return absl::InternalError("Illegal Dubbo message"); ++ } ++ } else { ++ response_buffer_.move(data); ++ } ++ ++ decodeDubboHeader(response_buffer_, response_header_); ++ ++ if ((response_header_.type_ & EVENT_BIT_ON) == EVENT_BIT_ON) { ++ response_buffer_.drain(DUBBO_HEADER_SIZE + static_cast(response_header_.length_)); ++ return absl::AbortedError("Heartbeat response should be aborted"); ++ } ++ ++ if ((static_cast(response_header_.length_) + DUBBO_HEADER_SIZE) > ++ response_buffer_.length()) { ++ return absl::OutOfRangeError("Invalid dubbo response size"); ++ } ++ ++ response_buffer_.drain(DUBBO_HEADER_SIZE); ++ std::string response; ++ response.reserve(response_header_.length_); ++ response.resize(response_header_.length_); ++ response_buffer_.copyOut(0, response_header_.length_, &response[0]); ++ response_buffer_.drain(response_header_.length_); ++ Hessian2::Decoder decoder(response); ++ auto type_value = decoder.decode(); ++ if (type_value == nullptr) { ++ return absl::InternalError("Cannot parse RpcResult type from buffer"); ++ } ++ ++ auto type = static_cast(*type_value); ++ auto [has_value, has_exception, has_attachment] = DubboUtility::resolveResponseFlag(type); ++ json http_json; ++ if (has_exception || has_value) { ++ auto response_value = decoder.decode(); ++ http_json[has_value ? HTTPResponseKey : HTTPResponseErrorKey] = ++ DubboUtility::hessian2Json(response_value.get()); ++ } ++ ++ if (has_attachment) { ++ auto attachment_value = decoder.decode(); ++ http_json[HTTPResponseAttachmentKey] = DubboUtility::hessian2Json(attachment_value.get()); ++ } ++ ++ data.add(http_json.dump()); ++ return absl::OkStatus(); ++} ++ ++absl::Status Http2DubboTranscoder::extractTranscoderParameters(Http::RequestHeaderMap& headers, ++ Buffer::Instance& body) { ++ ASSERT(!current_params_.has_value()); ++ ++ ENVOY_LOG(debug, "method name is {} method args count is {}", method_info_.name_, ++ method_info_.parameter_mapping_.size()); ++ ++ TypedParamsWithAttachment params_and_attachment; ++ params_and_attachment.parameter_types_.resize(method_info_.parameter_mapping_.size()); ++ params_and_attachment.arguments_.resize(method_info_.parameter_mapping_.size()); ++ ++ uint8_t current_path_binding_index = 1; ++ uint8_t current_params_index = 0; ++ using ParameterMapping = envoy::extensions::filters::http::http_dubbo_transcoder::v3:: ++ HttpDubboTranscoder::DubboMethodMapping::ParameterMapping; ++ json body_json; ++ if (!body.toString().empty()) { ++ // If the exception is not caught, a core dump error may occur ++ try { ++ body_json = json::parse(body.toString()); ++ } catch (json::parse_error& e) { ++ ENVOY_LOG(warn, "json::parse throw exception : {}", e.what()); ++ } ++ } ++ ++ for (const auto& parameter : method_info_.parameter_mapping_) { ++ const auto& extract_key = parameter.extract_key(); ++ ENVOY_LOG(debug, "parameter extract key {}", extract_key); ++ ++ std::string parameter_value; ++ switch (parameter.extract_key_spec()) { ++ case ParameterMapping::ALL_QUERY_PARAMETER: { ++ Http::Utility::QueryParams params = Http::Utility::parseQueryString(headers.getPathValue()); ++ if (params.empty()) { ++ return absl::InternalError("Error parsing query parameters"); ++ } ++ ++ if (!params.count(extract_key)) { ++ return absl::NotFoundError(fmt::format("The parameter {} could not be found", extract_key)); ++ } ++ parameter_value = params[extract_key]; ++ break; ++ } ++ case ParameterMapping::ALL_HEADER: { ++ auto result = headers.get(Http::LowerCaseString(extract_key)); ++ if (result.empty()) { ++ return absl::NotFoundError(fmt::format("The header {} could not be found", extract_key)); ++ } ++ parameter_value = std::string(result[0]->value().getStringView()); ++ break; ++ } ++ case ParameterMapping::ALL_PATH: { ++ if (current_path_binding_index > bindings_.size()) { ++ return absl::OutOfRangeError("Error parsing query parameters"); ++ } ++ parameter_value = bindings_.at(current_path_binding_index - 1).value; ++ current_path_binding_index++; ++ break; ++ } ++ case ParameterMapping::ALL_BODY: { ++ if (body_json.is_discarded() || body_json.is_null()) { ++ return absl::InvalidArgumentError("the body can not be parsed as json or body is empty."); ++ } else { ++ if (!extract_key.empty()) { ++ auto key = body_json.find(extract_key); ++ if (key == body_json.end()) { ++ return absl::NotFoundError( ++ fmt::format("The parameter {} could not be found", extract_key)); ++ } ++ params_and_attachment.arguments_[current_params_index] = *key; ++ } else { ++ params_and_attachment.arguments_[current_params_index] = body_json; ++ } ++ params_and_attachment.parameter_types_[current_params_index] = parameter.mapping_type(); ++ } ++ current_params_index++; ++ continue; ++ } ++ default: ++ return absl::UnimplementedError("Unsupported types"); ++ } ++ ++ ENVOY_LOG(debug, "parameter extract value {}, type {}", parameter_value, ++ parameter.mapping_type()); ++ ++ absl::optional result = ++ DubboUtility::convertStringToTypeValue(parameter_value, parameter.mapping_type()); ++ if (!result) { ++ return absl::InvalidArgumentError( ++ "can not transcode the request because the given param not match the type"); ++ } ++ ++ params_and_attachment.arguments_[current_params_index] = result.value(); ++ params_and_attachment.parameter_types_[current_params_index] = parameter.mapping_type(); ++ current_params_index++; ++ } ++ ++ ENVOY_LOG(debug, "method name is {} method args count is {}", method_info_.name_, ++ method_info_.parameter_mapping_.size()); ++ ++ if (method_info_.passthrough_all_headers_.has_value()) { ++ if (method_info_.passthrough_all_headers_.value()) { ++ headers.iterate( ++ [¶ms_and_attachment](const Http::HeaderEntry& header) -> Http::HeaderMap::Iterate { ++ const std::string& header_key = {header.key().getStringView().begin(), ++ header.key().getStringView().end()}; ++ params_and_attachment.attachment_[header_key] = header.value().getStringView(); ++ return Http::HeaderMap::Iterate::Continue; ++ }); ++ } ++ } else { ++ if (method_info_.passthrough_header_keys_.has_value()) { ++ for (const auto& key : method_info_.passthrough_header_keys_.value()) { ++ ++ auto result = headers.get(Http::LowerCaseString(key)); ++ if (result.empty()) { ++ return absl::NotFoundError(fmt::format("The header {} could not be found", key)); ++ } ++ params_and_attachment.attachment_[key] = result[0]->value().getStringView(); ++ } ++ } else { ++ ENVOY_LOG(debug, "passthrough_header_keys has no value"); ++ } ++ } ++ ++ if (!method_info_.service_group_.empty()) { ++ params_and_attachment.attachment_[AttachmentGroupKey] = method_info_.service_group_; ++ } ++ ++ current_params_.emplace(params_and_attachment); ++ return absl::OkStatus(); ++} ++ ++void Http2DubboTranscoder::encodeDubboFrameWithGenericCall(Buffer::Instance& data) { ++ // Encode dubbo data. ++ std::string encoded_data; ++ Hessian2::Encoder encoder(encoded_data); ++ ++ // Write dubbo header. ++ { ++ // Write the dubbo protocol: magic-number\type\serialization id\status. ++ data.writeBEInt(static_cast(DUBBO_MAGIC)); ++ data.writeBEInt(static_cast(TYPE_INFO)); ++ data.writeBEInt(static_cast(DEFAULT_REQUEST_STAT)); ++ ++ // Write the request id. ++ // TODO(zhaobingkun.zbk) ++ if (RequestId == ULONG_MAX) { ++ RequestId = 0; ++ } ++ data.writeBEInt(static_cast(++RequestId)); ++ } ++ ++ // Encode dubbo body. ++ { ++ // Encode: dubbo version\service name\service version. ++ encoder.encode(DubboDefaultProtocolVsersion); ++ encoder.encode(method_info_.service_name_); ++ encoder.encode(method_info_.service_version_.empty() ? DubboDefaultMethodVersion ++ : method_info_.service_version_); ++ // Encode: method name\parameter type, use generic call. ++ encoder.encode(DubboGenericMethodName); ++ encoder.encode(DubboGenericParamTypes); ++ ++ // Encode: arguments. ++ encoder.encode(method_info_.name_); ++ if (current_params_.has_value()) { ++ auto type_j = json(current_params_.value().parameter_types_); ++ DubboUtility::encodeParameterList(type_j, encoder); ++ ++ auto params_j = json(current_params_.value().arguments_); ++ DubboUtility::encodeParameterList(params_j, encoder); ++ } else { ++ ENVOY_LOG(debug, "The parameter is empty"); ++ } ++ } ++ ++ // Encode attachment. ++ { ++ if (!current_params_.value().attachment_.is_null()) { ++ DubboUtility::json2Hessian(current_params_.value().attachment_, encoder); ++ } else { ++ encoder.encodeMapBegin(""); ++ encoder.encodeMapEnd(); ++ } ++ } ++ ++ // Write the message data length. ++ data.writeBEInt(static_cast(encoded_data.size())); ++ ++ // Write body and attachment data. ++ data.add(encoded_data.c_str(), encoded_data.size()); ++ ++ ENVOY_LOG(debug, "encoded data is {} size is {} ", data.toString(), data.length()); ++} ++ ++inline bool Http2DubboTranscoder::validateMagicNumber(Buffer::Instance& data) { ++ return data.peekBEInt() == DUBBO_MAGIC; ++} ++ ++void Http2DubboTranscoder::decodeDubboHeader(Buffer::Instance& data, Header& dubbo_header) { ++ ASSERT(data.length() >= DUBBO_HEADER_SIZE); ++ ++ uint64_t start_position = 0; ++ dubbo_header.magic_ = data.peekBEInt(start_position); ++ ++ start_position += sizeof(dubbo_header.magic_); ++ dubbo_header.type_ = data.peekBEInt(start_position); ++ ++ start_position += sizeof(dubbo_header.type_); ++ dubbo_header.state_ = data.peekBEInt(start_position); ++ ++ start_position += sizeof(dubbo_header.state_); ++ dubbo_header.reqId_ = data.peekBEInt(start_position); ++ ++ start_position += sizeof(dubbo_header.reqId_); ++ dubbo_header.length_ = data.peekBEInt(start_position); ++} ++ ++void TranscodeFilter::initPerRouteConfig() { ++ const auto* route_local = ++ Http::Utility::resolveMostSpecificPerFilterConfig( ++ "envoy.filters.http.http_dubbo_transcoder", decoder_callbacks_->route()); ++ ++ per_route_config_ = route_local ? route_local : &config_; ++} ++ ++// transcoder filter impl ++Http::FilterHeadersStatus TranscodeFilter::decodeHeaders(Http::RequestHeaderMap& header, ++ bool end_stream) { ++ initPerRouteConfig(); ++ if (per_route_config_->disabled()) { ++ return Http::FilterHeadersStatus::Continue; ++ } ++ ++ ENVOY_STREAM_LOG(debug, "decodeHeaders:", *decoder_callbacks_); ++ ++ auto [status, transcoder] = per_route_config_->createTranscoder(header); ++ if (!status.ok()) { ++ ENVOY_STREAM_LOG(debug, "Failed to transcode request headers: {}", *decoder_callbacks_, ++ status.ToString()); ++ ++ if (status.code() == absl::StatusCode::kNotFound && ++ !per_route_config_->requestValidateOptions().reject_unknown_method()) { ++ ENVOY_LOG(debug, "Request is passed through without transcoding because it cannot be mapped " ++ "to a Dubbo method."); ++ return Http::FilterHeadersStatus::Continue; ++ } ++ error_ = true; ++ decoder_callbacks_->sendLocalReply(static_cast(Http::Code::InternalServerError), ++ status.ToString(), nullptr, absl::nullopt, ""); ++ return Http::FilterHeadersStatus::StopIteration; ++ } ++ ++ transcoder_.reset(transcoder); ++ ++ if (end_stream) { ++ Buffer::OwnedImpl empty_data; ++ status = transcoder_->extractTranscoderParameters(header, empty_data); ++ if (!status.ok()) { ++ ENVOY_LOG(warn, "Failed to resolve headers, error is {}", status.ToString()); ++ ++ // TODO(zhaobingkun.zbk) ++ Http::Code http_code = DubboUtility::convertStatusToHttpCode(status.code()); ++ error_ = true; ++ decoder_callbacks_->sendLocalReply(static_cast(http_code), status.ToString(), ++ nullptr, absl::nullopt, ""); ++ return Http::FilterHeadersStatus::StopIteration; ++ } ++ ++ Buffer::OwnedImpl data; ++ transcoder_->encodeDubboFrameWithGenericCall(data); ++ decoder_callbacks_->addDecodedData(data, true); ++ ENVOY_STREAM_LOG(debug, "sent dubbo frame", *decoder_callbacks_); ++ } ++ ++ // Modify the request method to use http.tcp connection pools. ++ header.setMethod(Http::Headers::get().MethodValues.Connect); ++ request_header_ = &header; ++ return Http::FilterHeadersStatus::Continue; ++} ++ ++Http::FilterDataStatus TranscodeFilter::decodeData(Buffer::Instance& data, bool end_stream) { ++ if (data.length() == 0) { ++ return Http::FilterDataStatus::Continue; ++ } ++ ++ if (!transcoder_ || error_) { ++ ENVOY_STREAM_LOG(debug, "Transcoder does not exist or an error occurred, end_stream: {}", ++ *decoder_callbacks_, end_stream); ++ ++ return Http::FilterDataStatus::Continue; ++ } ++ ++ const auto status = transcoder_->extractTranscoderParameters(*request_header_, data); ++ if (!status.ok()) { ++ ENVOY_LOG(warn, "Failed to auto mapping body, error is {}", status.ToString()); ++ ++ // TODO(zhaobingkun.zbk) ++ Http::Code http_code = DubboUtility::convertStatusToHttpCode(status.code()); ++ error_ = true; ++ decoder_callbacks_->sendLocalReply(static_cast(http_code), status.ToString(), ++ nullptr, absl::nullopt, ""); ++ return Http::FilterDataStatus::StopIterationNoBuffer; ++ } ++ ++ data.drain(data.length()); ++ transcoder_->encodeDubboFrameWithGenericCall(data); ++ ++ ENVOY_STREAM_LOG(debug, "encoded dubbo frame, length: {}, data: {}", *decoder_callbacks_, ++ data.length(), data.toString()); ++ ++ return Http::FilterDataStatus::Continue; ++} ++ ++Http::FilterTrailersStatus TranscodeFilter::decodeTrailers(Http::RequestTrailerMap&) { ++ return Http::FilterTrailersStatus::Continue; ++} ++ ++Http::FilterHeadersStatus TranscodeFilter::encodeHeaders(Http::ResponseHeaderMap&, bool) { ++ return Http::FilterHeadersStatus::Continue; ++} ++ ++Http::FilterDataStatus TranscodeFilter::encodeData(Buffer::Instance& data, bool end_stream) { ++ ENVOY_STREAM_LOG(debug, "Recieve data from remote {} length is {} end_stream is {}", ++ *decoder_callbacks_, data.toString(), data.length(), end_stream); ++ ++ if (transcoder_) { ++ absl::Status status = transcoder_->translateDubboToHttp(data); ++ if (!status.ok()) { ++ if (status.code() != absl::StatusCode::kAborted) { ++ Http::Code http_code = DubboUtility::convertStatusToHttpCode(status.code()); ++ error_ = true; ++ decoder_callbacks_->sendLocalReply(static_cast(http_code), status.ToString(), ++ nullptr, absl::nullopt, ""); ++ } ++ return Http::FilterDataStatus::StopIterationNoBuffer; ++ } ++ } ++ ++ return Http::FilterDataStatus::Continue; ++} ++ ++Http::FilterTrailersStatus TranscodeFilter::encodeTrailers(Http::ResponseTrailerMap&) { ++ if (transcoder_) { ++ transcoder_.reset(); ++ } ++ ++ return Http::FilterTrailersStatus::Continue; ++} ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.h b/contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.h +new file mode 100644 +index 0000000000..39ba90821e +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.h +@@ -0,0 +1,238 @@ ++#pragma once ++ ++#include ++#include ++#include ++ ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.h" ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.h" ++#include "contrib/http_dubbo_transcoder/filters/http/source/transcoder.h" ++#include "contrib/http_dubbo_transcoder/filters/http/source/utility.h" ++ ++#include "envoy/api/api.h" ++#include "envoy/http/filter.h" ++#include "envoy/type/matcher/v3/regex.pb.h" ++ ++#include "source/common/common/logger_impl.h" ++#include "source/common/common/logger.h" ++#include "source/common/common/regex.h" ++#include "source/common/http/codes.h" ++#include "source/common/http/header_map_impl.h" ++ ++#include "grpc_transcoding/path_matcher.h" ++ ++#include "hessian2/basic_codec/object_codec.hpp" ++#include "hessian2/codec.hpp" ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++class Http2DubboTranscoder; ++ ++/*** ++ * transcoder config ++ */ ++class DubboTranscoderConfig : public Router::RouteSpecificFilterConfig, ++ public Logger::Loggable { ++public: ++ /*** ++ * resolve the global enable falg in the config ++ */ ++ DubboTranscoderConfig( ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder& ++ config); ++ ++ /*** ++ * this function will create the corresponding transcoder acccording to the ++ * headers, mainly according to the content-type field ++ * ++ * @return nullptr if the any thing wrong when create transcoder ++ */ ++ std::tuple ++ createTranscoder(Http::RequestHeaderMap& headers) const; ++ ++ MethodInfoSharedPtr ++ createMethodInfo(const std::string& service_name, const std::string& service_version, ++ const std::string& service_group, ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3:: ++ HttpDubboTranscoder::DubboMethodMapping& method_mapping); ++ ++ /*** ++ * wether enable the transcoder ++ */ ++ bool disabled() const { return disabled_; } ++ ++ const envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder:: ++ RequestValidateOptions& ++ requestValidateOptions() const { ++ return request_validate_options_; ++ } ++ ++private: ++ bool disabled_{false}; ++ envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder:: ++ RequestValidateOptions request_validate_options_; ++ google::grpc::transcoding::PathMatcherPtr path_matcher_; ++}; ++ ++using DubboTranscoderConfigSharedPtr = std::shared_ptr; ++ ++/*** ++ * the error maybe occured while peoccsing the header or body ++ * 0 means no error ++ */ ++enum class ParamsErrorCode : int8_t { ++ OK = 0, ++ CountError = 1, ++ TypeError = 2, ++ ParseError = 4, ++ MethodNotFound = 5, ++ OthersError = 7, ++}; ++ ++// DUBBO HEADER FRAME ++struct Header { ++ uint16_t magic_; ++ uint8_t type_; ++ uint8_t state_; ++ int64_t reqId_; ++ int32_t length_; ++}; ++ ++constexpr uint64_t DUBBO_HEADER_SIZE = 16; ++constexpr uint64_t DUBBO_MAGIC_SIZE = 2; ++constexpr uint64_t DUBBO_TYPE_SIZE = 1; ++constexpr uint64_t DUBBO_STATE_SIZE = 1; ++constexpr uint64_t DUBBO_REQID_SIZE = 8; ++constexpr uint64_t DUBBO_PACKETLEN_SIZE = 4; ++constexpr uint16_t DUBBO_MAGIC = 0xdabb; ++constexpr uint8_t DEFAULT_REQUEST_STAT = 0; ++constexpr int64_t DEFAULT_REQUEST_ID = 1; ++/** ++ * ++ * | req or response | 2 way | event | Serializtion | ++ * | 1 | 1 | 0 | 2 | ++ * | 1 | 1 | 0 | 00010 | ++ * more details: ++ * https://dubbo.apache.org/en/blog/2018/10/05/introduction-to-the-dubbo-protocol/ ++ */ ++constexpr uint8_t TYPE_INFO = 0xc2; ++ ++// this type point to the state_ field in the Header struct ++enum class ResponseStatus : uint8_t { ++ Ok = 20, ++ ClientTimeout = 30, ++ ServerTimeout = 31, ++ BadRequest = 40, ++ BadResponse = 50, ++ ServiceNotFound = 60, ++ ServiceError = 70, ++ ServerError = 80, ++ ClientError = 90, ++ ServerThreadpoolExhaustedError = 100, ++}; ++ ++/*** ++ * Rpc response represent used by DubboDecoder ++ */ ++struct RpcResponse { ++ std::string body_; ++ Envoy::Http::Code code_; ++}; ++ ++using RpcResponsePtr = std::unique_ptr; ++ ++/*** ++ * this class transcode the http request to dubbo request ++ * the transcode support http2Dubbo specification ++ * the transcode split into 2 condition: ++ * 1. service map (one path corresponding to a set methods of a service) ++ * 2. method map (one path corresponding to one method) ++ */ ++class Http2DubboTranscoder : public Logger::Loggable { ++public: ++ /*** ++ * @param method_info_vec the correspond methodinfo of the request,come from sharedPtr of ++ * pathmatcher ++ * @param config the transcoder config ++ */ ++ Http2DubboTranscoder(const MethodInfo& method_info, std::vector&& bindings); ++ ++ std::string getName() const { return "http_dubbo_transcoder"; } ++ ++ absl::Status translateDubboToHttp(Buffer::Instance& data); ++ absl::Status extractTranscoderParameters(Http::RequestHeaderMap& headers, Buffer::Instance& body); ++ ++ void encodeDubboFrameWithGenericCall(Buffer::Instance& data); ++ ++private: ++ bool validateMagicNumber(Buffer::Instance& data); ++ void decodeDubboHeader(Buffer::Instance& data, Header& dubbo_header); ++ ++ struct TypedParamsWithAttachment { ++ std::vector parameter_types_; ++ std::vector arguments_; ++ nlohmann::json attachment_; ++ }; ++ ++ const MethodInfo& method_info_; ++ const std::vector bindings_; ++ Buffer::OwnedImpl request_buffer_{}; ++ Buffer::OwnedImpl response_buffer_{}; ++ Header response_header_; ++ absl::optional current_params_; ++}; ++ ++using Http2DubboTranscoderPtr = std::unique_ptr; ++ ++/*** ++ * Transcoder Filter ++ */ ++class TranscodeFilter : public Http::StreamFilter, public Logger::Loggable { ++public: ++ TranscodeFilter(DubboTranscoderConfig& config) : config_(config){}; ++ // Http::StreamFilterBase ++ void onDestroy() override{}; ++ ++ // Http::StreamDecoderFilter ++ Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& headers, ++ bool end_stream) override; ++ Http::FilterDataStatus decodeData(Buffer::Instance& data, bool end_stream) override; ++ Http::FilterTrailersStatus decodeTrailers(Http::RequestTrailerMap&) override; ++ void setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& callbacks) override { ++ decoder_callbacks_ = &callbacks; ++ } ++ ++ // Http::StreamEncoderFilter ++ Http::FilterHeadersStatus encode100ContinueHeaders(Http::ResponseHeaderMap&) override { ++ return Http::FilterHeadersStatus::Continue; ++ } ++ Http::FilterHeadersStatus encodeHeaders(Http::ResponseHeaderMap&, bool) override; ++ Http::FilterDataStatus encodeData(Buffer::Instance&, bool) override; ++ Http::FilterTrailersStatus encodeTrailers(Http::ResponseTrailerMap&) override; ++ Http::FilterMetadataStatus encodeMetadata(Http::MetadataMap&) override { ++ return Http::FilterMetadataStatus::Continue; ++ } ++ void setEncoderFilterCallbacks(Http::StreamEncoderFilterCallbacks& callbacks) override { ++ encoder_callbacks_ = &callbacks; ++ } ++ ++private: ++ void initPerRouteConfig(); ++ ++ Http2DubboTranscoderPtr transcoder_; ++ DubboTranscoderConfig& config_; ++ const DubboTranscoderConfig* per_route_config_{}; ++ Http::StreamEncoderFilterCallbacks* encoder_callbacks_{}; ++ Http::StreamDecoderFilterCallbacks* decoder_callbacks_{}; ++ Http::RequestHeaderMap* request_header_{}; ++ ++ bool error_{false}; ++}; ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/transcoder.h b/contrib/http_dubbo_transcoder/filters/http/source/transcoder.h +new file mode 100644 +index 0000000000..693de1fb4d +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/transcoder.h +@@ -0,0 +1,60 @@ ++#pragma once ++ ++#include ++ ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.h" ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.h" ++#include "envoy/http/filter.h" ++ ++#include "source/common/buffer/buffer_impl.h" ++#include "source/common/common/logger.h" ++#include "source/common/http/codes.h" ++#include "source/common/http/header_map_impl.h" ++ ++#include "absl/container/flat_hash_map.h" ++#include "absl/status/status.h" ++#include "include/nlohmann/json.hpp" ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++using Status = absl::Status; ++ ++/*** ++ * the Rpc invocation meta represent ++ */ ++ ++struct VariableBinding { ++ // the location the params in the dubbo request arg ++ std::vector field_path; ++ // The value to be inserted. ++ std::string value; ++}; ++using VariableBindingVecPtr = std::unique_ptr>; ++ ++using TypeAndFiledPath = std::pair>; ++ ++struct MethodInfo { ++ std::string service_name_; ++ std::string service_version_; ++ std::string service_group_; ++ std::string name_; ++ std::string match_http_method_; ++ std::string match_pattern_; ++ Protobuf::RepeatedPtrField ++ parameter_mapping_; ++ Protobuf::RepeatedPtrField attachment_from_header_keys_; ++ absl::optional passthrough_all_headers_; ++ absl::optional> passthrough_header_keys_; ++ bool passthrough_body_{false}; ++}; ++ ++using MethodInfoSharedPtr = std::shared_ptr; ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/utility.cc b/contrib/http_dubbo_transcoder/filters/http/source/utility.cc +new file mode 100644 +index 0000000000..8af0557a05 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/utility.cc +@@ -0,0 +1,284 @@ ++#include "utility.h" ++ ++#include ++#include ++ ++#include "envoy/http/codes.h" ++#include "envoy/http/query_params.h" ++ ++#include "source/common/buffer/buffer_impl.h" ++#include "source/common/common/enum_to_int.h" ++#include "source/common/common/regex.h" ++ ++#include "absl/strings/str_split.h" ++#include "hessian2/object.hpp" ++#include "include/nlohmann/json.hpp" ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++absl::optional DubboUtility::convertStringToTypeValue(absl::string_view value, ++ std::string type) { ++ ++ // the return value converted value maybe int boolean string, so use json to store the value ++ if (type == JsonType2JavaType.at(json::value_t::boolean)) { ++ if (value == "true" || value == "false") { ++ return {json(value == "true" ? true : false)}; ++ } ++ return absl::nullopt; ++ } else if (type == JsonType2JavaType.at(json::value_t::number_float)) { ++ envoy::type::matcher::v3::RegexMatcher matcher; ++ *matcher.mutable_google_re2() = envoy::type::matcher::v3::RegexMatcher::GoogleRE2(); ++ matcher.set_regex("^-?([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+|0)$"); ++ const auto compiled_matcher = Regex::Utility::parseRegex(matcher); ++ if (!compiled_matcher->match(value)) { ++ return absl::nullopt; ++ } ++ return {json(strtod(value.data(), nullptr))}; ++ } else if (type == JsonType2JavaType.at(json::value_t::number_integer)) { ++ envoy::type::matcher::v3::RegexMatcher matcher; ++ *matcher.mutable_google_re2() = envoy::type::matcher::v3::RegexMatcher::GoogleRE2(); ++ matcher.set_regex("^(0|[1-9][0-9]*|-[1-9][0-9]*)$"); ++ const auto compiled_matcher = Regex::Utility::parseRegex(matcher); ++ if (!compiled_matcher->match(value)) { ++ return absl::nullopt; ++ } ++ return {json(strtoll(value.data(), nullptr, 10))}; ++ } else if (type == JsonType2JavaType.at(json::value_t::string)) { ++ return {json(value)}; ++ } else if (type == JsonType2JavaType.at(json::value_t::array)) { ++ json array_json; ++ array_json.emplace_back(std::string(value)); ++ return array_json; ++ } else { ++ return absl::nullopt; ++ } ++} ++ ++Http::Code DubboUtility::convertStatusToHttpCode(absl::StatusCode status) { ++ Http::Code ret_http_code; ++ ++ switch (status) { ++ case absl::StatusCode::kInternal: ++ ret_http_code = Http::Code::InternalServerError; ++ break; ++ case absl::StatusCode::kNotFound: ++ ret_http_code = Http::Code::NotFound; ++ break; ++ case absl::StatusCode::kOutOfRange: ++ ret_http_code = Http::Code::RangeNotSatisfiable; ++ break; ++ case absl::StatusCode::kUnimplemented: ++ ret_http_code = Http::Code::NotImplemented; ++ break; ++ case absl::StatusCode::kInvalidArgument: ++ ret_http_code = Http::Code::BadRequest; ++ break; ++ case absl::StatusCode::kDataLoss: ++ ret_http_code = Http::Code::BadRequest; ++ break; ++ default: ++ ret_http_code = Http::Code::NotFound; ++ } ++ ++ return ret_http_code; ++} ++ ++std::tuple DubboUtility::resolveResponseFlag(RpcResponseType flag) { ++ bool has_value = false, has_excption = false, has_attachment = false; ++ ++ switch (flag) { ++ case RpcResponseType::ResponseWithException: ++ has_excption = true; ++ break; ++ case RpcResponseType::ResponseWithExceptionWithAttachments: ++ has_excption = true; ++ has_attachment = true; ++ break; ++ case RpcResponseType::ResponseWithNullValue: ++ has_value = false; ++ break; ++ case RpcResponseType::ResponseNullValueWithAttachments: ++ has_value = false; ++ has_attachment = true; ++ break; ++ case RpcResponseType::ResponseWithValue: ++ has_value = true; ++ break; ++ case RpcResponseType::ResponseValueWithAttachments: ++ has_value = true; ++ has_attachment = true; ++ break; ++ } ++ ++ return {has_value, has_excption, has_attachment}; ++} ++ ++json DubboUtility::hessian2Json(Object* input) { ++ json out; ++ ++ if (input == nullptr) { ++ out = NullValue; ++ return out; ++ } ++ ++ switch (input->type()) { ++ case Object::Type::TypedMap: ++ case Object::Type::UntypedMap: { ++ for (auto& item : input->asType()) { ++ Hessian2::StringObject& key = item.first->asType(); ++ if (key.toMutableString() != nullptr && *(key.toMutableString()) != ClassKey) { ++ out[*(key.toMutableString())] = hessian2Json(item.second.get()); ++ } ++ } ++ } break; ++ ++ case Object::Type::UntypedList: ++ case Object::Type::TypedList: { ++ for (auto& item : input->asType()) { ++ json j = hessian2Json(item.get()); ++ out.push_back(j); ++ } ++ } break; ++ ++ case Object::Type::String: { ++ out = *(input->asType().toMutableString()); ++ } break; ++ ++ case Object::Type::Double: { ++ out = *(input->asType().toMutableDouble()); ++ } break; ++ ++ case Object::Type::Integer: { ++ out = *(input->asType().toMutableInteger()); ++ } break; ++ ++ case Object::Type::Long: { ++ out = *(input->asType().toMutableLong()); ++ } break; ++ ++ case Object::Type::Boolean: { ++ out = *(input->asType().toMutableBoolean()); ++ } break; ++ ++ case Object::Type::Ref: { ++ out = hessian2Json((input->asType().toRefDest().value())); ++ } break; ++ ++ case Object::Type::Class: ++ out = input->toClassInstance().value()->def_->type_; ++ break; ++ ++ case Object::Type::Date: ++ out = input->toMutableDate()->count(); ++ break; ++ ++ case Object::Type::Null: ++ out = NullValue; ++ break; ++ ++ case Object::Type::Binary: ++ out = *(input->toMutableBinary()); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return out; ++} ++ ++void DubboUtility::json2Hessian(json&& object, Hessian2::Encoder& encoder) { ++ auto type = object.type(); ++ switch (type) { ++ case json::value_t::object: { ++ encoder.encodeMapBegin(""); ++ for (auto& el : object.items()) { ++ encoder.encode(el.key()); ++ json2Hessian(el.value(), encoder); ++ } ++ encoder.encodeMapEnd(); ++ } break; ++ ++ case json::value_t::boolean: ++ encoder.encode(object.get()); ++ break; ++ ++ case json::value_t::number_integer: ++ case json::value_t::number_unsigned: ++ encoder.encode(object.get()); ++ break; ++ ++ case json::value_t::number_float: ++ encoder.encode(object.get()); ++ break; ++ ++ case json::value_t::array: { ++ Hessian2::Object::UntypedList untyped_list; ++ for (auto& item : object.items()) { ++ createUntypedListObjcet(item.value(), untyped_list); ++ } ++ Hessian2::UntypedListObject untyped_list_object(std::move(untyped_list)); ++ encoder.encode(untyped_list_object); ++ } break; ++ ++ case json::value_t::string: ++ encoder.encode(object.get()); ++ break; ++ ++ case json::value_t::binary: ++ encoder.encode>(object.get_binary()); ++ break; ++ ++ case json::value_t::null: ++ default: ++ encoder.encode(Hessian2::NullObject()); ++ break; ++ } ++} ++ ++void DubboUtility::json2Hessian(json& j, Hessian2::Encoder& encoder) { ++ DubboUtility::json2Hessian(std::move(j), encoder); ++} ++ ++void DubboUtility::encodeParameterList(json& j, Hessian2::Encoder& encoder) { ++ encoder.encodeVarListBegin(""); ++ for (auto& item : j.items()) { ++ json2Hessian(item.value(), encoder); ++ } ++ encoder.encodeVarListEnd(); ++} ++ ++void DubboUtility::createUntypedListObjcet(const json& object, ++ Hessian2::Object::UntypedList& untyped_list) { ++ auto type = object.type(); ++ switch (type) { ++ case json::value_t::string: ++ untyped_list.emplace_back(std::make_unique(object.get())); ++ break; ++ case json::value_t::number_unsigned: ++ case json::value_t::number_integer: ++ untyped_list.emplace_back(std::make_unique(object.get())); ++ break; ++ case json::value_t::number_float: ++ untyped_list.emplace_back(std::make_unique(object.get())); ++ break; ++ case json::value_t::boolean: ++ untyped_list.emplace_back(std::make_unique(object.get())); ++ break; ++ case json::value_t::binary: ++ untyped_list.emplace_back(std::make_unique(object.get_binary())); ++ break; ++ case json::value_t::null: ++ default: ++ untyped_list.emplace_back(std::make_unique()); ++ break; ++ } ++} ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/source/utility.h b/contrib/http_dubbo_transcoder/filters/http/source/utility.h +new file mode 100644 +index 0000000000..bd7c197468 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/source/utility.h +@@ -0,0 +1,88 @@ ++#pragma once ++#include ++#include ++ ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.h" ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.h" ++#include "envoy/http/codes.h" ++#include "envoy/http/query_params.h" ++ ++#include "source/common/buffer/buffer_impl.h" ++#include "source/common/common/enum_to_int.h" ++#include "source/common/common/regex.h" ++#include "source/common/http/utility.h" ++ ++#include "hessian2/basic_codec/object_codec.hpp" ++#include "hessian2/object.hpp" ++#include "include/nlohmann/json.hpp" ++#include "transcoder.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++using json = nlohmann::json; ++using Object = Hessian2::Object; ++using ObjectPtr = std::unique_ptr; ++using ListObject = Hessian2::UntypedListObject; ++using ListObjectPtr = std::unique_ptr; ++using StringObject = Hessian2::StringObject; ++using StringObjectPtr = std::unique_ptr; ++using MapObject = Hessian2::UntypedMapObject; ++using MapObjectPtr = std::unique_ptr; ++ ++static const std::string NullValue = "null"; ++static const std::string ClassKey = "class"; ++ ++static const absl::flat_hash_map JsonType2JavaType{ ++ {json::value_t::number_integer, "java.lang.Long"}, ++ {json::value_t::number_unsigned, "java.lang.Long"}, ++ {json::value_t::string, "java.lang.String"}, ++ {json::value_t::boolean, "java.lang.Boolean"}, ++ {json::value_t::array, "java.util.List"}, ++ {json::value_t::object, "java.util.Map"}, ++ {json::value_t::number_float, "java.lang.Double"}, ++ {json::value_t::null, ""}, ++}; ++ ++// the first byte in the response body express the response type ++enum class RpcResponseType : uint8_t { ++ ResponseWithException = 0, ++ ResponseWithValue = 1, ++ ResponseWithNullValue = 2, ++ ResponseWithExceptionWithAttachments = 3, ++ ResponseValueWithAttachments = 4, ++ ResponseNullValueWithAttachments = 5, ++}; ++ ++class DubboUtility { ++public: ++ /*** ++ * this is a tool funtion convert a string view value to the given type value ++ * now just support base type: ++ * 1. Integer ++ * 2. Boolean ++ * 3. Double ++ * 4. String ++ * ++ * other types will return absl::nullopt ++ * @return the true value represent by json ++ * ++ */ ++ static absl::optional convertStringToTypeValue(absl::string_view, std::string); ++ static Http::Code convertStatusToHttpCode(absl::StatusCode status); ++ ++ // hessian2 json translate ++ static json hessian2Json(Object* obj); ++ static void json2Hessian(json&& j, Hessian2::Encoder& encoder); ++ static void json2Hessian(json& j, Hessian2::Encoder& encoder); ++ static void encodeParameterList(json& j, Hessian2::Encoder& encoder); ++ static void createUntypedListObjcet(const json& object, Hessian2::Object::UntypedList& untyped_list); ++ static std::tuple resolveResponseFlag(RpcResponseType flag); ++}; ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/test/BUILD b/contrib/http_dubbo_transcoder/filters/http/test/BUILD +new file mode 100644 +index 0000000000..ee22ba5512 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/test/BUILD +@@ -0,0 +1,31 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_test", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_test( ++ name = "config_test", ++ srcs = ["config_test.cc"], ++ deps = [ ++ "//contrib/http_dubbo_transcoder/filters/http/source:config", ++ "//test/mocks/server:factory_context_mocks", ++ "//test/test_common:utility_lib", ++ "@envoy_api//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg_cc_proto", ++ ], ++) ++ ++envoy_cc_test( ++ name = "dubbo_transcoder_filter_test", ++ srcs = ["dubbo_transcoder_filter_test.cc"], ++ deps = [ ++ "//contrib/http_dubbo_transcoder/filters/http/source:config", ++ "//test/mocks/server:factory_context_mocks", ++ "//test/test_common:utility_lib", ++ "@envoy_api//contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/http_dubbo_transcoder/filters/http/test/config_test.cc b/contrib/http_dubbo_transcoder/filters/http/test/config_test.cc +new file mode 100644 +index 0000000000..a8a224284d +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/test/config_test.cc +@@ -0,0 +1,80 @@ ++#include "test/mocks/server/factory_context.h" ++#include "test/test_common/utility.h" ++ ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.h" ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.h" ++#include "contrib/http_dubbo_transcoder/filters/http/source/config.h" ++#include "contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.h" ++ ++#include "gmock/gmock.h" ++#include "gtest/gtest.h" ++ ++using testing::_; ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++TEST(HttpDubboTranscodeFilterFactoryTest, HttpDubboTranscodeFilterCorrectYaml) { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: true ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++)EOF"; ++ ++ envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder proto_config; ++ TestUtility::loadFromYaml(yaml_string, proto_config); ++ NiceMock context; ++ HttpDubboTranscodeFilterFactory factory; ++ Http::FilterFactoryCb cb = factory.createFilterFactoryFromProto(proto_config, "stats", context); ++ Http::MockFilterChainFactoryCallbacks filter_callback; ++ EXPECT_CALL(filter_callback, addStreamFilter(_)); ++ cb(filter_callback); ++} ++ ++TEST(HttpDubboTranscodeFilterFactoryTest, HttpDubboTranscodePerFilterCorrectYaml) { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: true ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++)EOF"; ++ ++ envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder proto_config; ++ TestUtility::loadFromYaml(yaml_string, proto_config); ++ NiceMock context; ++ HttpDubboTranscodeFilterFactory factory; ++ auto route_config = factory.createRouteSpecificFilterConfig( ++ proto_config, context, ProtobufMessage::getStrictValidationVisitor()); ++ const auto* config = dynamic_cast(route_config.get()); ++ EXPECT_FALSE(config->disabled()); ++} ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/test/dubbo_transcoder_filter_test.cc b/contrib/http_dubbo_transcoder/filters/http/test/dubbo_transcoder_filter_test.cc +new file mode 100644 +index 0000000000..32fb08ffe8 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/test/dubbo_transcoder_filter_test.cc +@@ -0,0 +1,754 @@ ++#include "test/mocks/server/factory_context.h" ++#include "test/test_common/utility.h" ++ ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.h" ++#include "contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.h" ++#include "contrib/http_dubbo_transcoder/filters/http/source/config.h" ++#include "contrib/http_dubbo_transcoder/filters/http/source/dubbo_transcoder_filter.h" ++#include "contrib/http_dubbo_transcoder/filters/http/source/utility.h" ++ ++#include "gmock/gmock.h" ++#include "gtest/gtest.h" ++ ++using testing::_; ++ ++namespace Envoy { ++namespace Extensions { ++namespace HttpFilters { ++namespace HttpDubboTranscoder { ++ ++class TranscodeFilterTest : public testing::Test { ++public: ++ TranscodeFilterTest() = default; ++ ++ void setConfiguration() { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++)EOF"; ++ ++ setConfiguration(yaml_string); ++ } ++ ++ void setConfiguration(const std::string& yaml_string) { ++ envoy::extensions::filters::http::http_dubbo_transcoder::v3::HttpDubboTranscoder proto_config; ++ TestUtility::loadFromYaml(yaml_string, proto_config); ++ ++ time_system_.setSystemTime(std::chrono::seconds(1610503040)); ++ config_ = std::make_shared(proto_config); ++ } ++ ++ void setFilter() { setFilter(std::make_shared(*config_)); } ++ ++ void setFilter(std::shared_ptr filter) { ++ filter_ = filter; ++ filter_->setDecoderFilterCallbacks(decoder_callbacks_); ++ filter_->setEncoderFilterCallbacks(encoder_callbacks_); ++ } ++ ++ Stats::TestUtil::TestStore scope_; ++ Event::SimulatedTimeSystem time_system_; ++ NiceMock decoder_callbacks_; ++ NiceMock encoder_callbacks_; ++ std::shared_ptr config_; ++ std::shared_ptr filter_; ++}; ++ ++TEST_F(TranscodeFilterTest, NormalHttpGetMethod) { ++ setConfiguration(); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(1); ++ ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_param=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++} ++ ++TEST_F(TranscodeFilterTest, AllowUnknownMethodAndParameter) { ++ setConfiguration(); ++ setFilter(); ++ ++ { ++ // the path mismatch. ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "POST"}, ++ {":path", "/mytest.service/test?my_param=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Post, request_headers.getMethodValue()); ++ } ++ ++ { ++ // the parameter mismatch. ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/mytest.service/test?my_test=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Get, request_headers.getMethodValue()); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, RejectUnknownMethodAndParameter) { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: true ++ reject_unknown_method: true ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++)EOF"; ++ ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ { ++ // the path mismatch. ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(1); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "POST"}, ++ {":path", "/mytest.service/test?my_param=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Post, request_headers.getMethodValue()); ++ } ++ ++ { ++ // the parameter mismatch. ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(1); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_test=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Get, request_headers.getMethodValue()); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, ExtractParameterKeyFromQuery) { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param1 ++ mapping_type: "java.lang.String" ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param2 ++ mapping_type: "java.lang.Long" ++)EOF"; ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ { ++ // normal request ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(1); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_param1=test&my_param2=12345"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ } ++ { ++ // the request path don't include a query ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::InternalServerError, _, _, _, _)) ++ .Times(1); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/mytest.service/sayHello"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Get, request_headers.getMethodValue()); ++ } ++ ++ { ++ // query key don't match the extract_key ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::NotFound, _, _, _, _)).Times(1); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_param1=test&my_param4=45645"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Get, request_headers.getMethodValue()); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, ExtractParameterKeyFromHeader) { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param1 ++ mapping_type: "java.lang.String" ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param2 ++ mapping_type: "java.lang.Double" ++)EOF"; ++ setConfiguration(yaml_string); ++ setFilter(); ++ { ++ // normal request ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(1); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/mytest.service/sayHello"}, ++ {"my_param1", "test"}, ++ {"my_param2", "0.234"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ } ++ { ++ // extract_key my_param1 cannot be found in headers ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::NotFound, _, _, _, _)).Times(1); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/mytest.service/sayHello"}, ++ {"param", "test"}, ++ {"my_param2", "0.234"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Get, request_headers.getMethodValue()); ++ } ++ { ++ // my_param2's mapping type is Double, but given String ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::BadRequest, _, _, _, _)).Times(1); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/mytest.service/sayHello"}, ++ {"my_param1", "test"}, ++ {"my_param2", "abc"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Get, request_headers.getMethodValue()); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, DefaultMatchingPathAndHttpMethod) { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param1 ++ mapping_type: "java.lang.String" ++)EOF"; ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ { ++ // normal request ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(1); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/common.sayHello/sayHello"}, {"my_param1", "test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ } ++ ++ { ++ // extract_key my_param1 cannot be found in headers ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::NotFound, _, _, _, _)).Times(1); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/common.sayHello/sayHello"}, {"param", "test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Get, request_headers.getMethodValue()); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, ExtractParameterKeyFromBody) { ++ { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_BODY ++ extract_key: name ++ mapping_type: "java.lang.String" ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param1 ++ mapping_type: "java.lang.String" ++)EOF"; ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, _)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/common.sayHello/sayHello"}, {"my_param1", "test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, false)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ ++ std::string json_string = R"EOF( ++ { ++ "age": 10, ++ "name" : "test" ++ } ++ )EOF"; ++ Buffer::OwnedImpl data(json_string); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); ++ ++ std::string encoded_data(data.toString()); ++ EXPECT_TRUE(encoded_data.find("test") != std::string::npos); ++ } ++ ++ { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_BODY ++ mapping_type: "java.util.Map" ++)EOF"; ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, _)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/common.sayHello/sayHello"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, false)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ ++ std::string json_string = R"EOF( ++ { ++ "age": 10, ++ "name" : "test" ++ } ++ )EOF"; ++ Buffer::OwnedImpl data(json_string); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); ++ ++ std::string encoded_data(data.toString()); ++ EXPECT_TRUE(encoded_data.find("age") != std::string::npos); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, PassthroughSetting) { ++ { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_BODY ++ extract_key: name ++ mapping_type: "java.lang.String" ++ passthrough_setting: ++ passthrough_all_headers: true ++)EOF"; ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/common.sayHello/sayHello"}, {"my_param1", "test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, false)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ ++ std::string json_string = R"EOF( ++ { ++ "age": 10, ++ "name" : "test" ++ } ++ )EOF"; ++ Buffer::OwnedImpl data(json_string); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); ++ ++ std::string encoded_data(data.toString()); ++ EXPECT_TRUE(encoded_data.find("my_param1") != std::string::npos); ++ EXPECT_TRUE(encoded_data.find("sayHello") != std::string::npos); ++ } ++ ++ { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_BODY ++ extract_key: name ++ mapping_type: "java.lang.String" ++ passthrough_setting: ++ passthrough_all_headers: false ++)EOF"; ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/common.sayHello/sayHello"}, {"my_param1", "test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, false)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ ++ std::string json_string = R"EOF( ++ { ++ "age": 10, ++ "name" : "test" ++ } ++ )EOF"; ++ Buffer::OwnedImpl data(json_string); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); ++ ++ std::string encoded_data(data.toString()); ++ EXPECT_TRUE(encoded_data.find("my_param1") == std::string::npos); ++ EXPECT_TRUE(encoded_data.find("GET") == std::string::npos); ++ } ++} ++ ++TEST(DobboUtilityTest, convertStringToTypeValueTest) { ++ { ++ absl::string_view value{"0.234234"}; ++ std::string type{"java.lang.Double"}; ++ nlohmann::json result = 0.234234; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++ { ++ absl::string_view value{"-0.234234"}; ++ std::string type{"java.lang.Double"}; ++ nlohmann::json result = -0.234234; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++ { ++ absl::string_view value{"0.0"}; ++ std::string type{"java.lang.Double"}; ++ nlohmann::json result = 0; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++ ++ { ++ absl::string_view value{"837465"}; ++ std::string type{"java.lang.Long"}; ++ nlohmann::json result = 837465; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++ { ++ absl::string_view value{"-34534"}; ++ std::string type{"java.lang.Long"}; ++ nlohmann::json result = -34534; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++ { ++ absl::string_view value{"0"}; ++ std::string type{"java.lang.Long"}; ++ nlohmann::json result = 0; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++ { ++ absl::string_view value{"true"}; ++ std::string type{"java.lang.Boolean"}; ++ nlohmann::json result = true; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++ { ++ absl::string_view value{"false"}; ++ std::string type{"java.lang.Boolean"}; ++ nlohmann::json result = false; ++ EXPECT_EQ(result, DubboUtility::convertStringToTypeValue(value, type).value()); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, EncodeDataFromDubboServer) { ++ setConfiguration(); ++ setFilter(); ++ ++ // initialize filter_->transcoder by calling filter->decodeHeaders ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_param=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ ++ { ++ // 1. Normal dubbo request message ++ Buffer::OwnedImpl buffer; ++ buffer.add(std::string({'\xda', '\xbb', 0x42, 20})); ++ buffer.writeBEInt(static_cast(1)); ++ std::string content({'I', 0x00, 0x00, 0x00, 0x01, 0x05, 'h', 'e', 'l', 'l', 'o'}); ++ buffer.writeBEInt(static_cast(content.size())); ++ buffer.add(content); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_EQ(filter_->encodeData(buffer, true), Http::FilterDataStatus::Continue); ++ } ++ ++ { ++ // 2. Response is divided into header and body ++ Buffer::OwnedImpl response_header; ++ response_header.add(std::string({'\xda', '\xbb', 0x42, 20})); ++ response_header.writeBEInt(static_cast(1)); ++ std::string content({'I', 0x00, 0x00, 0x00, 0x01, 0x05, 'h', 'e', 'l', 'l', 'o'}); ++ response_header.writeBEInt(static_cast(content.size())); ++ // recieve dubbo header ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::RangeNotSatisfiable, _, _, _, _)) ++ .Times(1); ++ EXPECT_EQ(filter_->encodeData(response_header, true), ++ Http::FilterDataStatus::StopIterationNoBuffer); ++ Buffer::OwnedImpl response_body; ++ response_body.add(content); ++ // recieve dubbo body ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_EQ(filter_->encodeData(response_body, true), Http::FilterDataStatus::Continue); ++ } ++ ++ { ++ // 3. The header is split into two parts, and the second part is sent along with the body ++ Buffer::OwnedImpl response_header; ++ response_header.add(std::string({'\xda', '\xbb', 0x42, 20})); ++ response_header.writeBEInt(static_cast(1)); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::BadRequest, _, _, _, _)).Times(1); ++ EXPECT_EQ(filter_->encodeData(response_header, true), ++ Http::FilterDataStatus::StopIterationNoBuffer); ++ ++ std::string content({'I', 0x00, 0x00, 0x00, 0x01, 0x05, 'h', 'e', 'l', 'l', 'o'}); ++ Buffer::OwnedImpl response_body; ++ response_body.writeBEInt(static_cast(content.size())); ++ response_body.add(content); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_EQ(filter_->encodeData(response_body, true), Http::FilterDataStatus::Continue); ++ } ++ { ++ // 4. The body is split into two parts, with the first part sent along with the header ++ Buffer::OwnedImpl response_header; ++ response_header.add(std::string({'\xda', '\xbb', 0x42, 20})); ++ response_header.writeBEInt(static_cast(1)); ++ std::string content({'I', 0x00, 0x00, 0x00, 0x01, 0x05, 'h', 'e', 'l', 'l', 'o'}); ++ response_header.writeBEInt(static_cast(content.size())); ++ response_header.add(std::string({'I', 0x00, 0x00, 0x00, 0x01, 0x05})); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::RangeNotSatisfiable, _, _, _, _)) ++ .Times(1); ++ EXPECT_EQ(filter_->encodeData(response_header, true), ++ Http::FilterDataStatus::StopIterationNoBuffer); ++ ++ Buffer::OwnedImpl response_body; ++ response_body.add(std::string({'h', 'e', 'l', 'l', 'o'})); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_EQ(filter_->encodeData(response_body, true), Http::FilterDataStatus::Continue); ++ } ++ { ++ // 5. The whole response is divided into three parts ++ Buffer::OwnedImpl response_header; ++ response_header.add(std::string({'\xda', '\xbb', 0x42, 20})); ++ response_header.writeBEInt(static_cast(1)); ++ std::string content({'I', 0x00, 0x00, 0x00, 0x01, 0x05, 'h', 'e', 'l', 'l', 'o'}); ++ response_header.writeBEInt(static_cast(content.size())); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::RangeNotSatisfiable, _, _, _, _)) ++ .Times(1); ++ EXPECT_EQ(filter_->encodeData(response_header, true), ++ Http::FilterDataStatus::StopIterationNoBuffer); ++ ++ Buffer::OwnedImpl body_part1; ++ body_part1.add(std::string({'I', 0x00, 0x00, 0x00, 0x01})); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::RangeNotSatisfiable, _, _, _, _)) ++ .Times(1); ++ EXPECT_EQ(filter_->encodeData(body_part1, true), Http::FilterDataStatus::StopIterationNoBuffer); ++ ++ Buffer::OwnedImpl body_part2; ++ body_part2.add(std::string({0x05, 'h', 'e', 'l', 'l', 'o'})); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_EQ(filter_->encodeData(body_part2, true), Http::FilterDataStatus::Continue); ++ } ++ { ++ // 6. Cannot parse RpcResult type from buffer ++ Buffer::OwnedImpl buffer; ++ buffer.add(std::string({'\xda', '\xbb', 0x42, 20})); ++ buffer.writeBEInt(static_cast(1)); ++ std::string content({0x00, 0x00, 0x00, 0x01, 0x05, 'h', 'e', 'l', 'l', 'o'}); ++ buffer.writeBEInt(static_cast(content.size())); ++ buffer.add(content); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(Http::Code::InternalServerError, _, _, _, _)) ++ .Times(1); ++ EXPECT_EQ(filter_->encodeData(buffer, true), Http::FilterDataStatus::StopIterationNoBuffer); ++ } ++ { ++ // 7. Heartbeat event ++ Buffer::OwnedImpl buffer; ++ buffer.add(std::string({'\xda', '\xbb', 0x62, 20})); // event bit is set to 1 ++ buffer.writeBEInt(static_cast(1)); ++ buffer.writeBEInt(static_cast(0)); ++ EXPECT_CALL(decoder_callbacks_, sendLocalReply(_, _, _, _, _)).Times(0); ++ EXPECT_EQ(filter_->encodeData(buffer, true), Http::FilterDataStatus::StopIterationNoBuffer); ++ } ++} ++ ++TEST_F(TranscodeFilterTest, ServiceVersionAndGroup) { ++ { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++)EOF"; ++ ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(1); ++ ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_param=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ } ++ { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++)EOF"; ++ ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(1); ++ ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_param=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ } ++ { ++ const std::string yaml_string = R"EOF( ++url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++request_validation_options: ++ reject_unknown_query_parameters: false ++ reject_unknown_method: false ++services_mapping: ++- name: "common.sayHello" ++ group: "dev" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++)EOF"; ++ ++ setConfiguration(yaml_string); ++ setFilter(); ++ ++ EXPECT_CALL(decoder_callbacks_, addDecodedData(_, true)).Times(1); ++ ++ Http::TestRequestHeaderMapImpl request_headers{ ++ {":method", "GET"}, {":path", "/mytest.service/sayHello?my_param=test"}}; ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); ++ EXPECT_EQ(Http::Headers::get().MethodValues.Connect, request_headers.getMethodValue()); ++ } ++} ++ ++} // namespace HttpDubboTranscoder ++} // namespace HttpFilters ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo.yaml b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo.yaml +new file mode 100644 +index 0000000000..ba754d86e1 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo.yaml +@@ -0,0 +1,100 @@ ++static_resources: ++ listeners: ++ - address: ++ socket_address: ++ address: 0.0.0.0 ++ port_value: 80 ++ filter_chains: ++ - filters: ++ - name: envoy.filters.network.http_connection_manager ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager ++ codec_type: auto ++ stat_prefix: ingress_http ++ http_protocol_options: ++ accept_http_10: true ++ route_config: ++ name: local_route ++ virtual_hosts: ++ - name: service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/abc" ++ route: ++ cluster: local_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ - match: ++ prefix: "/mytest_1" ++ route: ++ cluster: local_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ http_filters: ++ - name: envoy.filters.http.http_dubbo_transcoder ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.Transcoder ++ disable: false ++ auto_map: true ++ url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++ request_validation_options: ++ reject_unknown_query_parameters: true ++ services: ++ - name: "common.sayHello" ++ version: "0.0.0" ++ methods: ++ get: "/abc/{path.name}" ++ name: "sayHello" ++ maps: ++ - name: "path.name" ++ mapTo: "params.0" ++ type: "java.lang.String" ++ - name: "common.sayHello" ++ version: "0.0.0" ++ map_service_url: /mytest_* ++ methods: ++ get: "{header.name}" ++ name: "sayHello" ++ body_template: "" ++ maps: ++ - name: "header.name" ++ mapTo: "params.0" ++ type: "java.lang.String" ++ - name: envoy.filters.http.router ++ typed_config: {} ++ clusters: ++ - name: local_service ++ connect_timeout: 5s ++ type: strict_dns ++ lb_policy: round_robin ++ upstream_config: ++ name: envoy.upstreams.http.tcp ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.upstreams.http.tcp.v3.TcpConnectionPoolProto ++ load_assignment: ++ cluster_name: local_service ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: 11.164.30.21 ++ port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 139.162.123.134 ++ # port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 114.55.31.224 ++ # port_value: 20880 +\ No newline at end of file +diff --git a/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_new.yaml b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_new.yaml +new file mode 100644 +index 0000000000..81c0578135 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_new.yaml +@@ -0,0 +1,228 @@ ++static_resources: ++ listeners: ++ - address: ++ socket_address: ++ address: 0.0.0.0 ++ port_value: 3344 ++ filter_chains: ++ - filters: ++ - name: envoy.filters.network.http_connection_manager ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager ++ codec_type: auto ++ stat_prefix: ingress_http ++ http_protocol_options: ++ accept_http_10: true ++ route_config: ++ name: local_route ++ virtual_hosts: ++ - name: service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/demoservice.DemoService" ++ route: ++ cluster: local_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ - match: ++ prefix: "/mytest.service" ++ route: ++ cluster: local_test_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ http_filters: ++ - name: envoy.filters.http.http_dubbo_transcoder ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder ++ url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++ request_validation_options: ++ reject_unknown_query_parameters: true ++ services_mapping: ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "org.apache.dubbo.samples.basic.api.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello11" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ passthrough_setting: ++ passthrough_all_headers: true ++ passthrough_body: true ++ - name: "org.apache.dubbo.samples.basic.api.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "getEchoxx" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello22" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.util.List" ++ passthrough_setting: ++ passthrough_all_headers: true ++ passthrough_body: true ++ - name: "org.apache.dubbo.samples.basic.api.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "getEcho" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello33" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param1 ++ mapping_type: "java.util.List" ++ passthrough_setting: ++ passthrough_all_headers: true ++ passthrough_body: true ++ - name: "org.apache.dubbo.samples.basic.api.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "getEcho" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello44" ++ match_http_method_spec: ALL_POST ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ passthrough_setting: ++ passthrough_all_headers: true ++ passthrough_body: true ++ - name: "org.apache.dubbo.samples.basic.api.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "mapEcho" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello55" ++ match_http_method_spec: ALL_POST ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ passthrough_setting: ++ passthrough_headers: ++ keys: ++ - "token" ++ passthrough_body: true ++ - name: "org.apache.dubbo.demo.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "getEcho" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHelloxxxxx" ++ match_http_method_spec: ALL_POST ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "org.apache.dubbo.demo.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_POST ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param_1 ++ mapping_type: "java.lang.String" ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param_2 ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/demoservice.DemoService/sayHello/{my_param}" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_PATH ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/demoservice.DemoService/sayHello/{my_param}" ++ match_http_method_spec: ALL_GET ++ - name: envoy.filters.http.router ++ typed_config: {} ++ clusters: ++ - name: local_test_service ++ connect_timeout: 5s ++ type: strict_dns ++ lb_policy: round_robin ++ upstream_config: ++ name: envoy.upstreams.http.dubbo_tcp ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.upstreams.http.dubbo_tcp.v3.DubboTcpConnectionPoolProto ++ load_assignment: ++ cluster_name: local_service ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: 30.225.8.108 ++ port_value: 20880 ++ - name: local_service ++ connect_timeout: 5s ++ type: strict_dns ++ lb_policy: round_robin ++ upstream_config: ++ name: envoy.upstreams.http.dubbo_tcp ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.upstreams.http.dubbo_tcp.v3.DubboTcpConnectionPoolProto ++ load_assignment: ++ cluster_name: local_service ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: 30.225.8.108 ++ port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 139.162.123.134 ++ # port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 114.55.31.224 ++ # port_value: 20880 +\ No newline at end of file +diff --git a/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_pre_route copy.yaml b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_pre_route copy.yaml +new file mode 100644 +index 0000000000..1e928ae8a0 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_pre_route copy.yaml +@@ -0,0 +1,151 @@ ++static_resources: ++ listeners: ++ - address: ++ socket_address: ++ address: 0.0.0.0 ++ port_value: 80 ++ filter_chains: ++ - filters: ++ - name: envoy.filters.network.http_connection_manager ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager ++ codec_type: auto ++ stat_prefix: ingress_http ++ http_protocol_options: ++ accept_http_10: true ++ route_config: ++ name: local_route ++ virtual_hosts: ++ - name: service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/demoservice.DemoService" ++ route: ++ cluster: local_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ - match: ++ prefix: "/mytest.service" ++ route: ++ cluster: local_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ typed_per_filter_config: ++ envoy.filters.http.http_dubbo_transcoder: ++ "@type": type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder ++ auto_mapping: true ++ url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++ request_validation_options: ++ reject_unknown_query_parameters: true ++ services_mapping: ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: key1 ++ mapping_type: "java.lang.String" ++ http_filters: ++ - name: envoy.filters.http.http_dubbo_transcoder ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder ++ auto_mapping: true ++ url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++ request_validation_options: ++ reject_unknown_query_parameters: true ++ services_mapping: ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_POST ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param_1 ++ mapping_type: "java.lang.String" ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param_2 ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/demoservice.DemoService/sayHello/{my_param}" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_PATH ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/demoservice.DemoService/sayHello/{my_param}" ++ match_http_method_spec: ALL_GET ++ attachment_from_header_keys: ++ - header_key_1 ++ - name: envoy.filters.http.router ++ typed_config: {} ++ clusters: ++ - name: local_service ++ connect_timeout: 5s ++ type: strict_dns ++ lb_policy: round_robin ++ upstream_config: ++ name: envoy.upstreams.http.tcp ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.upstreams.http.tcp.v3.TcpConnectionPoolProto ++ load_assignment: ++ cluster_name: local_service ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: 11.164.30.21 ++ port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 139.162.123.134 ++ # port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 114.55.31.224 ++ # port_value: 20880 +\ No newline at end of file +diff --git a/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_pre_route.yaml b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_pre_route.yaml +new file mode 100644 +index 0000000000..b574b70de1 +--- /dev/null ++++ b/contrib/http_dubbo_transcoder/filters/http/test/test_data/dubbo_pre_route.yaml +@@ -0,0 +1,166 @@ ++static_resources: ++ listeners: ++ - address: ++ socket_address: ++ address: 0.0.0.0 ++ port_value: 80 ++ filter_chains: ++ - filters: ++ - name: envoy.filters.network.http_connection_manager ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager ++ codec_type: auto ++ stat_prefix: ingress_http ++ http_protocol_options: ++ accept_http_10: true ++ route_config: ++ name: local_route ++ virtual_hosts: ++ - name: service ++ domains: ++ - "*" ++ typed_per_filter_config: ++ envoy.filters.http.http_dubbo_transcoder: ++ "@type": type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder ++ auto_mapping: true ++ url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++ request_validation_options: ++ reject_unknown_query_parameters: true ++ services_mapping: ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: key1 ++ mapping_type: "java.lang.String" ++ routes: ++ - match: ++ prefix: "/demoservice.DemoService" ++ route: ++ cluster: local_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ - match: ++ prefix: "/mytest.service" ++ route: ++ cluster: local_service ++ upgrade_configs: ++ - upgrade_type: "CONNECT" ++ connect_config: ++ allow_post: true ++ typed_per_filter_config: ++ envoy.filters.http.http_dubbo_transcoder: ++ "@type": type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder ++ services_mapping: ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello222" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: key1 ++ mapping_type: "java.lang.String" ++ http_filters: ++ - name: envoy.filters.http.http_dubbo_transcoder ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder ++ auto_mapping: true ++ url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED ++ request_validation_options: ++ reject_unknown_query_parameters: true ++ services_mapping: ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "common.sayHello" ++ version: "0.0.0" ++ method_mapping: ++ name: "getEcho" ++ path_matcher: ++ match_pattern: "/mytest.service/sayHello" ++ match_http_method_spec: ALL_POST ++ parameter_mapping: ++ - extract_key_spec: ALL_QUERY_PARAMETER ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ parameter_mapping: ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param_1 ++ mapping_type: "java.lang.String" ++ - extract_key_spec: ALL_HEADER ++ extract_key: my_param_2 ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/demoservice.DemoService/sayHello/{my_param}" ++ match_http_method_spec: ALL_GET ++ parameter_mapping: ++ - extract_key_spec: ALL_PATH ++ extract_key: my_param ++ mapping_type: "java.lang.String" ++ - name: "demoservice.DemoService" ++ version: "0.0.0" ++ method_mapping: ++ name: "sayHello" ++ path_matcher: ++ match_pattern: "/demoservice.DemoService/sayHello/{my_param}" ++ match_http_method_spec: ALL_GET ++ attachment_from_header_keys: ++ - header_key_1 ++ - name: envoy.filters.http.router ++ typed_config: {} ++ clusters: ++ - name: local_service ++ connect_timeout: 5s ++ type: strict_dns ++ lb_policy: round_robin ++ upstream_config: ++ name: envoy.upstreams.http.tcp ++ typed_config: ++ "@type": type.googleapis.com/envoy.extensions.upstreams.http.tcp.v3.TcpConnectionPoolProto ++ load_assignment: ++ cluster_name: local_service ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: 11.164.30.21 ++ port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 139.162.123.134 ++ # port_value: 20880 ++ # - lb_endpoints: ++ # - endpoint: ++ # address: ++ # socket_address: ++ # address: 114.55.31.224 ++ # port_value: 20880 +\ No newline at end of file +diff --git a/contrib/server/admin/source/BUILD b/contrib/server/admin/source/BUILD +new file mode 100644 +index 0000000000..04e9191fb6 +--- /dev/null ++++ b/contrib/server/admin/source/BUILD +@@ -0,0 +1,28 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_library", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_library( ++ name = "cluster_endpoints_handler_lib", ++ srcs = ["cluster_endpoints_handler.cc"], ++ hdrs = ["cluster_endpoints_handler.h"], ++ visibility = ["//visibility:public"], ++ deps = [ ++ "//envoy/http:codes_interface", ++ "//envoy/server:admin_interface", ++ "//envoy/server:instance_interface", ++ "//source/common/buffer:buffer_lib", ++ "//source/common/http:codes_lib", ++ "//source/common/http:header_map_lib", ++ "//source/common/upstream:host_utility_lib", ++ "//source/server/admin:handler_ctx_lib", ++ "//source/server/admin:utils_lib", ++ "@envoy_api//envoy/admin/v3:pkg_cc_proto", ++ ], ++) +diff --git a/contrib/server/admin/source/cluster_endpoints_handler.cc b/contrib/server/admin/source/cluster_endpoints_handler.cc +new file mode 100644 +index 0000000000..5b73fbbd81 +--- /dev/null ++++ b/contrib/server/admin/source/cluster_endpoints_handler.cc +@@ -0,0 +1,76 @@ ++#include "contrib/server/admin/source/cluster_endpoints_handler.h" ++ ++#include "envoy/admin/v3/clusters.pb.h" ++ ++#include "source/common/http/headers.h" ++#include "source/common/http/utility.h" ++#include "source/common/network/utility.h" ++#include "source/common/upstream/host_utility.h" ++#include "source/server/admin/utils.h" ++ ++namespace Envoy { ++namespace Server { ++ ++namespace {} // namespace ++ ++ClusterEndpointsHandler::ClusterEndpointsHandler(Server::Instance& server) ++ : HandlerContextBase(server) {} ++ ++Http::Code ClusterEndpointsHandler::handlerClusterEndpoints(absl::string_view path, ++ Http::HeaderMap&, ++ Buffer::Instance& response, ++ AdminStream& admin_stream) { ++ Http::Utility::QueryParams params = Http::Utility::parseQueryString(path); ++ if (params.empty()) { ++ // Check if the params are in the request's body.}{} ++ if (admin_stream.getRequestBody() != nullptr && ++ isFormUrlEncoded(admin_stream.getRequestHeaders().ContentType())) { ++ params = Http::Utility::parseFromBody(admin_stream.getRequestBody()->toString()); ++ } ++ } ++ ++ absl::optional service_name = ++ params.find("service") != params.end() ++ ? absl::optional{params.at("service")} ++ : absl::nullopt; ++ ++ if (params.empty() || !service_name.has_value()) { ++ response.add("usage: /endpoints?service=value1&protocol=value2\n"); ++ response.add(" or send the parameters as form values\n"); ++ response.add("use an empty value to remove a previously added override"); ++ return Http::Code::BadRequest; ++ } ++ ++ auto all_clusters = server_.clusterManager().clusters(); ++ for (const auto& [name, cluster_ref] : all_clusters.active_clusters_) { ++ // const Upstream::Cluster& cluster = cluster_pair.second.get(); ++ const Upstream::Cluster& cluster = cluster_ref.get(); ++ Upstream::ClusterInfoConstSharedPtr cluster_info = cluster.info(); ++ if (absl::StrContains(cluster_info->name(), service_name.value())) { ++ response.add(fmt::format("ClusterName: {}\n", cluster_info->name())); ++ for (auto& host_set : cluster.prioritySet().hostSetsPerPriority()) { ++ for (auto& host : host_set->hosts()) { ++ response.add(fmt::format("\tendpoint: {}", host->address()->asString())); ++ response.add( ++ fmt::format("\tmetadata: {}\n", ++ host->metadata() == nullptr ++ ? std::string() ++ : MessageUtil::getJsonStringFromMessageOrDie(*host->metadata()))); ++ } ++ } ++ } ++ } ++ return Http::Code::OK; ++} ++ ++bool ClusterEndpointsHandler::isFormUrlEncoded(const Http::HeaderEntry* content_type) const { ++ if (content_type == nullptr) { ++ return false; ++ } ++ ++ return content_type->value().getStringView() == ++ Http::Headers::get().ContentTypeValues.FormUrlEncoded; ++} ++ ++} // namespace Server ++} // namespace Envoy +diff --git a/contrib/server/admin/source/cluster_endpoints_handler.h b/contrib/server/admin/source/cluster_endpoints_handler.h +new file mode 100644 +index 0000000000..13ba0108bf +--- /dev/null ++++ b/contrib/server/admin/source/cluster_endpoints_handler.h +@@ -0,0 +1,30 @@ ++#pragma once ++ ++#include "envoy/buffer/buffer.h" ++#include "envoy/http/codes.h" ++#include "envoy/http/header_map.h" ++#include "envoy/server/admin.h" ++#include "envoy/server/instance.h" ++ ++#include "source/server/admin/handler_ctx.h" ++ ++#include "absl/strings/string_view.h" ++ ++namespace Envoy { ++namespace Server { ++ ++class ClusterEndpointsHandler : public HandlerContextBase { ++ ++public: ++ ClusterEndpointsHandler(Server::Instance& server); ++ ++ Http::Code handlerClusterEndpoints(absl::string_view path_and_query, ++ Http::HeaderMap& response_headers, Buffer::Instance& response, ++ AdminStream&); ++ ++private: ++ bool isFormUrlEncoded(const Http::HeaderEntry* content_type) const; ++}; ++ ++} // namespace Server ++} // namespace Envoy +diff --git a/contrib/sip_proxy/filters/network/source/router/router_impl.h b/contrib/sip_proxy/filters/network/source/router/router_impl.h +index 231d94c7a6..c51ccb1f0e 100644 +--- a/contrib/sip_proxy/filters/network/source/router/router_impl.h ++++ b/contrib/sip_proxy/filters/network/source/router/router_impl.h +@@ -241,7 +241,7 @@ public: + std::shared_ptr getUpstreamRequest(const std::string& host) { + try { + return tls_->getTyped().upstream_request_map_.at(host); +- } catch (std::out_of_range) { ++ } catch (std::out_of_range const&) { + return nullptr; + } + } +diff --git a/contrib/upstreams/http/dubbo_tcp/source/BUILD b/contrib/upstreams/http/dubbo_tcp/source/BUILD +new file mode 100644 +index 0000000000..6c07446efa +--- /dev/null ++++ b/contrib/upstreams/http/dubbo_tcp/source/BUILD +@@ -0,0 +1,54 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_contrib_extension", ++ "envoy_cc_library", ++ "envoy_contrib_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_contrib_package() ++ ++envoy_cc_contrib_extension( ++ name = "config", ++ srcs = [ ++ "config.cc", ++ ], ++ hdrs = [ ++ "config.h", ++ ], ++ visibility = ["//visibility:public"], ++ deps = [ ++ ":upstream_request_lib", ++ "@envoy_api//contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3:pkg_cc_proto", ++ ], ++) ++ ++envoy_cc_library( ++ name = "upstream_request_lib", ++ srcs = [ ++ "upstream_request.cc", ++ ], ++ hdrs = [ ++ "upstream_request.h", ++ ], ++ visibility = ["//visibility:public"], ++ deps = [ ++ "//envoy/http:codes_interface", ++ "//envoy/http:filter_interface", ++ "//envoy/upstream:upstream_interface", ++ "//source/common/common:assert_lib", ++ "//source/common/common:minimal_logger_lib", ++ "//source/common/common:utility_lib", ++ "//source/common/http:codes_lib", ++ "//source/common/http:header_map_lib", ++ "//source/common/http:headers_lib", ++ "//source/common/http:message_lib", ++ "//source/common/network:application_protocol_lib", ++ "//source/common/network:transport_socket_options_lib", ++ "//source/common/router:router_lib", ++ "//source/common/upstream:load_balancer_lib", ++ "//source/extensions/common/proxy_protocol:proxy_protocol_header_lib", ++ "//source/extensions/upstreams/http/tcp:upstream_request_lib", ++ ], ++) +diff --git a/contrib/upstreams/http/dubbo_tcp/source/config.cc b/contrib/upstreams/http/dubbo_tcp/source/config.cc +new file mode 100644 +index 0000000000..163c85b892 +--- /dev/null ++++ b/contrib/upstreams/http/dubbo_tcp/source/config.cc +@@ -0,0 +1,27 @@ ++#include "config.h" ++ ++#include "upstream_request.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace Upstreams { ++namespace Http { ++namespace DubboTcp { ++ ++Router::GenericConnPoolPtr DubboTcpGenericConnPoolFactory::createGenericConnPool( ++ Upstream::ThreadLocalCluster& thread_local_cluster, bool is_connect, ++ const Router::RouteEntry& route_entry, ++ absl::optional downstream_protocol, ++ Upstream::LoadBalancerContext* ctx) const { ++ auto ret = std::make_unique(thread_local_cluster, is_connect, route_entry, ++ downstream_protocol, ctx); ++ return (ret->valid() ? std::move(ret) : nullptr); ++} ++ ++REGISTER_FACTORY(DubboTcpGenericConnPoolFactory, Router::GenericConnPoolFactory); ++ ++} // namespace DubboTcp ++} // namespace Http ++} // namespace Upstreams ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/upstreams/http/dubbo_tcp/source/config.h b/contrib/upstreams/http/dubbo_tcp/source/config.h +new file mode 100644 +index 0000000000..c889847566 +--- /dev/null ++++ b/contrib/upstreams/http/dubbo_tcp/source/config.h +@@ -0,0 +1,37 @@ ++#pragma once ++ ++#include "contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.pb.h" ++#include "envoy/registry/registry.h" ++#include "envoy/router/router.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace Upstreams { ++namespace Http { ++namespace DubboTcp { ++ ++/** ++ * Config registration for the TcpConnPool. @see Router::GenericConnPoolFactory ++ */ ++class DubboTcpGenericConnPoolFactory : public Router::GenericConnPoolFactory { ++public: ++ std::string name() const override { return "envoy.filters.connection_pools.http.dubbo_tcp"; } ++ std::string category() const override { return "envoy.upstreams"; } ++ Router::GenericConnPoolPtr ++ createGenericConnPool(Upstream::ThreadLocalCluster& thread_local_cluster, bool is_connect, ++ const Router::RouteEntry& route_entry, ++ absl::optional downstream_protocol, ++ Upstream::LoadBalancerContext* ctx) const override; ++ ProtobufTypes::MessagePtr createEmptyConfigProto() override { ++ return std::make_unique< ++ envoy::extensions::upstreams::http::dubbo_tcp::v3::DubboTcpConnectionPoolProto>(); ++ } ++}; ++ ++DECLARE_FACTORY(DubboTcpGenericConnPoolFactory); ++ ++} // namespace DubboTcp ++} // namespace Http ++} // namespace Upstreams ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/upstreams/http/dubbo_tcp/source/upstream_request.cc b/contrib/upstreams/http/dubbo_tcp/source/upstream_request.cc +new file mode 100644 +index 0000000000..ec484af45a +--- /dev/null ++++ b/contrib/upstreams/http/dubbo_tcp/source/upstream_request.cc +@@ -0,0 +1,119 @@ ++#include "upstream_request.h" ++ ++#include ++#include ++ ++#include "envoy/upstream/upstream.h" ++ ++#include "source/common/common/assert.h" ++#include "source/common/common/utility.h" ++#include "source/common/http/codes.h" ++#include "source/common/http/header_map_impl.h" ++#include "source/common/http/headers.h" ++#include "source/common/http/message_impl.h" ++#include "source/common/network/transport_socket_options_impl.h" ++#include "source/common/router/router.h" ++#include "source/extensions/common/proxy_protocol/proxy_protocol_header.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace Upstreams { ++namespace Http { ++namespace DubboTcp { ++ ++void TcpConnPool::onPoolReady(Envoy::Tcp::ConnectionPool::ConnectionDataPtr&& conn_data, ++ Upstream::HostDescriptionConstSharedPtr host) { ++ upstream_handle_ = nullptr; ++ Network::Connection& latched_conn = conn_data->connection(); ++ auto upstream = ++ std::make_unique(&callbacks_->upstreamToDownstream(), std::move(conn_data)); ++ callbacks_->onPoolReady(std::move(upstream), host, ++ latched_conn.connectionInfoProvider().localAddress(), ++ latched_conn.streamInfo(), {}); ++} ++ ++TcpUpstream::TcpUpstream(Router::UpstreamToDownstream* upstream_request, ++ Envoy::Tcp::ConnectionPool::ConnectionDataPtr&& upstream) ++ : upstream_request_(upstream_request), upstream_conn_data_(std::move(upstream)) { ++ upstream_conn_data_->connection().enableHalfClose(false); ++ upstream_conn_data_->addUpstreamCallbacks(*this); ++} ++ ++void TcpUpstream::encodeData(Buffer::Instance& data, bool end_stream) { ++ end_stream = false; ++ upstream_conn_data_->connection().write(data, end_stream); ++} ++ ++Envoy::Http::Status TcpUpstream::encodeHeaders(const Envoy::Http::RequestHeaderMap&, ++ bool end_stream) { ++ // Headers should only happen once, so use this opportunity to add the proxy ++ // proto header, if configured. ++ const Router::RouteEntry* route_entry = upstream_request_->route().routeEntry(); ++ ASSERT(route_entry != nullptr); ++ if (route_entry->connectConfig().has_value()) { ++ Buffer::OwnedImpl data; ++ auto& connect_config = route_entry->connectConfig().value(); ++ if (connect_config.has_proxy_protocol_config()) { ++ Extensions::Common::ProxyProtocol::generateProxyProtoHeader( ++ connect_config.proxy_protocol_config(), upstream_request_->connection(), data); ++ } ++ ++ if (data.length() != 0 || end_stream) { ++ upstream_conn_data_->connection().write(data, end_stream); ++ } ++ } ++ ++ // TcpUpstream::encodeHeaders is called after the UpstreamRequest is fully initialized. Alsoc use ++ // this time to synthesize the 200 response headers downstream to complete the CONNECT handshake. ++ Envoy::Http::ResponseHeaderMapPtr headers{ ++ Envoy::Http::createHeaderMap( ++ {{Envoy::Http::Headers::get().Status, "200"}})}; ++ upstream_request_->decodeHeaders(std::move(headers), false); ++ return Envoy::Http::okStatus(); ++} ++ ++void TcpUpstream::encodeTrailers(const Envoy::Http::RequestTrailerMap&) { ++ Buffer::OwnedImpl data; ++ upstream_conn_data_->connection().write(data, true); ++} ++ ++void TcpUpstream::readDisable(bool disable) { ++ if (upstream_conn_data_->connection().state() != Network::Connection::State::Open) { ++ return; ++ } ++ upstream_conn_data_->connection().readDisable(disable); ++} ++ ++void TcpUpstream::resetStream() { ++ upstream_request_ = nullptr; ++ upstream_conn_data_->connection().close(Network::ConnectionCloseType::NoFlush); ++} ++ ++void TcpUpstream::onUpstreamData(Buffer::Instance& data, bool end_stream) { ++ end_stream = true; ++ upstream_request_->decodeData(data, end_stream); ++} ++ ++void TcpUpstream::onEvent(Network::ConnectionEvent event) { ++ if (event != Network::ConnectionEvent::Connected && upstream_request_) { ++ upstream_request_->onResetStream(Envoy::Http::StreamResetReason::ConnectionTermination, ""); ++ } ++} ++ ++void TcpUpstream::onAboveWriteBufferHighWatermark() { ++ if (upstream_request_) { ++ upstream_request_->onAboveWriteBufferHighWatermark(); ++ } ++} ++ ++void TcpUpstream::onBelowWriteBufferLowWatermark() { ++ if (upstream_request_) { ++ upstream_request_->onBelowWriteBufferLowWatermark(); ++ } ++} ++ ++} // namespace DubboTcp ++} // namespace Http ++} // namespace Upstreams ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/upstreams/http/dubbo_tcp/source/upstream_request.h b/contrib/upstreams/http/dubbo_tcp/source/upstream_request.h +new file mode 100644 +index 0000000000..527b26190b +--- /dev/null ++++ b/contrib/upstreams/http/dubbo_tcp/source/upstream_request.h +@@ -0,0 +1,98 @@ ++#pragma once ++ ++#include ++#include ++ ++#include "envoy/http/codec.h" ++#include "envoy/tcp/conn_pool.h" ++#include "envoy/upstream/thread_local_cluster.h" ++ ++#include "source/common/buffer/watermark_buffer.h" ++#include "source/common/common/cleanup.h" ++#include "source/common/common/logger.h" ++#include "source/common/config/well_known_names.h" ++#include "source/common/router/upstream_request.h" ++#include "source/common/stream_info/stream_info_impl.h" ++#include "source/extensions/upstreams/http/tcp/upstream_request.h" ++ ++namespace Envoy { ++namespace Extensions { ++namespace Upstreams { ++namespace Http { ++namespace DubboTcp { ++ ++class TcpConnPool : public Router::GenericConnPool, public Envoy::Tcp::ConnectionPool::Callbacks { ++public: ++ TcpConnPool(Upstream::ThreadLocalCluster& thread_local_cluster, bool is_connect, ++ const Router::RouteEntry& route_entry, absl::optional, ++ Upstream::LoadBalancerContext* ctx) { ++ ASSERT(is_connect); ++ conn_pool_data_ = thread_local_cluster.tcpConnPool(route_entry.priority(), ctx); ++ } ++ void newStream(Router::GenericConnectionPoolCallbacks* callbacks) override { ++ callbacks_ = callbacks; ++ upstream_handle_ = conn_pool_data_.value().newConnection(*this); ++ } ++ ++ bool cancelAnyPendingStream() override { ++ if (upstream_handle_) { ++ upstream_handle_->cancel(Envoy::Tcp::ConnectionPool::CancelPolicy::Default); ++ upstream_handle_ = nullptr; ++ return true; ++ } ++ return false; ++ } ++ Upstream::HostDescriptionConstSharedPtr host() const override { ++ return conn_pool_data_.value().host(); ++ } ++ ++ bool valid() { return conn_pool_data_.has_value(); } ++ ++ // Tcp::ConnectionPool::Callbacks ++ void onPoolFailure(ConnectionPool::PoolFailureReason reason, ++ absl::string_view transport_failure_reason, ++ Upstream::HostDescriptionConstSharedPtr host) override { ++ upstream_handle_ = nullptr; ++ callbacks_->onPoolFailure(reason, transport_failure_reason, host); ++ } ++ ++ void onPoolReady(Envoy::Tcp::ConnectionPool::ConnectionDataPtr&& conn_data, ++ Upstream::HostDescriptionConstSharedPtr host) override; ++ ++private: ++ absl::optional conn_pool_data_; ++ Envoy::Tcp::ConnectionPool::Cancellable* upstream_handle_{}; ++ Router::GenericConnectionPoolCallbacks* callbacks_{}; ++}; ++ ++class TcpUpstream : public Router::GenericUpstream, ++ public Envoy::Tcp::ConnectionPool::UpstreamCallbacks { ++public: ++ TcpUpstream(Router::UpstreamToDownstream* upstream_request, ++ Envoy::Tcp::ConnectionPool::ConnectionDataPtr&& upstream); ++ ++ // GenericUpstream ++ void encodeData(Buffer::Instance& data, bool end_stream) override; ++ void encodeMetadata(const Envoy::Http::MetadataMapVector&) override {} ++ Envoy::Http::Status encodeHeaders(const Envoy::Http::RequestHeaderMap&, bool end_stream) override; ++ void encodeTrailers(const Envoy::Http::RequestTrailerMap&) override; ++ void readDisable(bool disable) override; ++ void resetStream() override; ++ void setAccount(Buffer::BufferMemoryAccountSharedPtr) override {} ++ ++ // Tcp::ConnectionPool::UpstreamCallbacks ++ void onUpstreamData(Buffer::Instance& data, bool end_stream) override; ++ void onEvent(Network::ConnectionEvent event) override; ++ void onAboveWriteBufferHighWatermark() override; ++ void onBelowWriteBufferLowWatermark() override; ++ ++private: ++ Router::UpstreamToDownstream* upstream_request_; ++ Envoy::Tcp::ConnectionPool::ConnectionDataPtr upstream_conn_data_; ++}; ++ ++} // namespace DubboTcp ++} // namespace Http ++} // namespace Upstreams ++} // namespace Extensions ++} // namespace Envoy +diff --git a/contrib/upstreams/http/dubbo_tcp/test/BUILD b/contrib/upstreams/http/dubbo_tcp/test/BUILD +new file mode 100644 +index 0000000000..3629142ff6 +--- /dev/null ++++ b/contrib/upstreams/http/dubbo_tcp/test/BUILD +@@ -0,0 +1,33 @@ ++load( ++ "//bazel:envoy_build_system.bzl", ++ "envoy_cc_test", ++ "envoy_package", ++) ++ ++licenses(["notice"]) # Apache 2 ++ ++envoy_package() ++ ++envoy_cc_test( ++ name = "upstream_request_test", ++ srcs = ["upstream_request_test.cc"], ++ deps = [ ++ "//contrib/upstreams/http/dubbo_tcp/source:upstream_request_lib", ++ "//source/common/buffer:buffer_lib", ++ "//source/common/network:address_lib", ++ "//source/common/router:router_lib", ++ "//source/common/upstream:upstream_includes", ++ "//source/common/upstream:upstream_lib", ++ "//test/common/http:common_lib", ++ "//test/mocks:common_lib", ++ "//test/mocks/network:network_mocks", ++ "//test/mocks/router:router_filter_interface", ++ "//test/mocks/router:router_mocks", ++ "//test/mocks/server:factory_context_mocks", ++ "//test/mocks/server:instance_mocks", ++ "//test/mocks/upstream:upstream_mocks", ++ "//test/test_common:environment_lib", ++ "//test/test_common:simulated_time_system_lib", ++ "//test/test_common:utility_lib", ++ ], ++) +diff --git a/contrib/upstreams/http/dubbo_tcp/test/upstream_request_test.cc b/contrib/upstreams/http/dubbo_tcp/test/upstream_request_test.cc +new file mode 100644 +index 0000000000..b42a54afa8 +--- /dev/null ++++ b/contrib/upstreams/http/dubbo_tcp/test/upstream_request_test.cc +@@ -0,0 +1,280 @@ ++#include "source/common/buffer/buffer_impl.h" ++#include "source/common/network/address_impl.h" ++#include "source/common/router/config_impl.h" ++#include "source/common/router/router.h" ++#include "source/common/router/upstream_request.h" ++#include "source/extensions/common/proxy_protocol/proxy_protocol_header.h" ++ ++#include "contrib/upstreams/http/dubbo_tcp/source/upstream_request.h" ++ ++#include "test/common/http/common.h" ++#include "test/mocks/common.h" ++#include "test/mocks/router/mocks.h" ++#include "test/mocks/router/router_filter_interface.h" ++#include "test/mocks/server/factory_context.h" ++#include "test/mocks/server/instance.h" ++#include "test/mocks/tcp/mocks.h" ++#include "test/test_common/utility.h" ++ ++#include "gmock/gmock.h" ++#include "gtest/gtest.h" ++ ++using Envoy::Http::TestRequestHeaderMapImpl; ++using Envoy::Router::UpstreamRequest; ++using testing::_; ++using testing::AnyNumber; ++using testing::NiceMock; ++using testing::Return; ++using testing::ReturnRef; ++ ++namespace Envoy { ++namespace Extensions { ++namespace Upstreams { ++namespace Http { ++namespace DubboTcp { ++ ++class TcpConnPoolTest : public ::testing::Test { ++public: ++ TcpConnPoolTest() : host_(std::make_shared>()) { ++ NiceMock route_entry; ++ NiceMock cm; ++ cm.initializeThreadLocalClusters({"fake_cluster"}); ++ EXPECT_CALL(cm.thread_local_cluster_, tcpConnPool(_, _)) ++ .WillOnce(Return(Upstream::TcpPoolData([]() {}, &mock_pool_))); ++ conn_pool_ = std::make_unique(cm.thread_local_cluster_, true, route_entry, ++ Envoy::Http::Protocol::Http11, nullptr); ++ } ++ ++ std::unique_ptr conn_pool_; ++ Envoy::Tcp::ConnectionPool::MockInstance mock_pool_; ++ Router::MockGenericConnectionPoolCallbacks mock_generic_callbacks_; ++ std::shared_ptr> host_; ++ NiceMock cancellable_; ++}; ++ ++TEST_F(TcpConnPoolTest, Basic) { ++ NiceMock connection; ++ ++ EXPECT_CALL(mock_pool_, newConnection(_)).WillOnce(Return(&cancellable_)); ++ conn_pool_->newStream(&mock_generic_callbacks_); ++ ++ EXPECT_CALL(mock_generic_callbacks_, upstreamToDownstream()); ++ EXPECT_CALL(mock_generic_callbacks_, onPoolReady(_, _, _, _, _)); ++ auto data = std::make_unique>(); ++ EXPECT_CALL(*data, connection()).Times(AnyNumber()).WillRepeatedly(ReturnRef(connection)); ++ conn_pool_->onPoolReady(std::move(data), host_); ++} ++ ++TEST_F(TcpConnPoolTest, OnPoolFailure) { ++ EXPECT_CALL(mock_pool_, newConnection(_)).WillOnce(Return(&cancellable_)); ++ conn_pool_->newStream(&mock_generic_callbacks_); ++ ++ EXPECT_CALL(mock_generic_callbacks_, onPoolFailure(_, "foo", _)); ++ conn_pool_->onPoolFailure(Envoy::Tcp::ConnectionPool::PoolFailureReason::LocalConnectionFailure, ++ "foo", host_); ++ ++ // Make sure that the pool failure nulled out the pending request. ++ EXPECT_FALSE(conn_pool_->cancelAnyPendingStream()); ++} ++ ++TEST_F(TcpConnPoolTest, Cancel) { ++ // Initially cancel should fail as there is no pending request. ++ EXPECT_FALSE(conn_pool_->cancelAnyPendingStream()); ++ ++ EXPECT_CALL(mock_pool_, newConnection(_)).WillOnce(Return(&cancellable_)); ++ conn_pool_->newStream(&mock_generic_callbacks_); ++ ++ // Canceling should now return true as there was an active request. ++ EXPECT_TRUE(conn_pool_->cancelAnyPendingStream()); ++ ++ // A second cancel should return false as there is not a pending request. ++ EXPECT_FALSE(conn_pool_->cancelAnyPendingStream()); ++} ++ ++class TcpUpstreamTest : public ::testing::Test { ++public: ++ TcpUpstreamTest() { ++ EXPECT_CALL(mock_router_filter_, downstreamHeaders()) ++ .Times(AnyNumber()) ++ .WillRepeatedly(Return(&request_)); ++ EXPECT_CALL(mock_router_filter_, cluster()).Times(AnyNumber()); ++ mock_router_filter_.requests_.push_back(std::make_unique( ++ mock_router_filter_, std::make_unique>())); ++ auto data = std::make_unique>(); ++ EXPECT_CALL(*data, connection()).Times(AnyNumber()).WillRepeatedly(ReturnRef(connection_)); ++ tcp_upstream_ = ++ std::make_unique(mock_router_filter_.requests_.front().get(), std::move(data)); ++ } ++ ~TcpUpstreamTest() override { EXPECT_CALL(mock_router_filter_, config()).Times(AnyNumber()); } ++ ++protected: ++ TestRequestHeaderMapImpl request_{{":method", "CONNECT"}, ++ {":path", "/"}, ++ {":protocol", "bytestream"}, ++ {":scheme", "https"}, ++ {":authority", "host"}}; ++ NiceMock connection_; ++ NiceMock mock_router_filter_; ++ Envoy::Tcp::ConnectionPool::MockConnectionData* mock_connection_data_; ++ std::unique_ptr tcp_upstream_; ++}; ++ ++TEST_F(TcpUpstreamTest, Basic) { ++ // Swallow the request headers and generate response headers. ++ EXPECT_CALL(connection_, write(_, false)).Times(0); ++ EXPECT_CALL(mock_router_filter_, onUpstreamHeaders(200, _, _, false)); ++ EXPECT_TRUE(tcp_upstream_->encodeHeaders(request_, false).ok()); ++ ++ // Proxy the data. ++ EXPECT_CALL(connection_, write(BufferStringEqual("foo"), false)); ++ Buffer::OwnedImpl buffer("foo"); ++ tcp_upstream_->encodeData(buffer, false); ++ ++ // Metadata is swallowed. ++ Envoy::Http::MetadataMapVector metadata_map_vector; ++ tcp_upstream_->encodeMetadata(metadata_map_vector); ++ ++ // Forward data. ++ Buffer::OwnedImpl response1("bar"); ++ // The dubbo forces end_stream to be true in the onupStreamData function. ++ EXPECT_CALL(mock_router_filter_, onUpstreamData(BufferStringEqual("bar"), _, true)); ++ tcp_upstream_->onUpstreamData(response1, false); ++} ++ ++TEST_F(TcpUpstreamTest, V1Header) { ++ envoy::config::core::v3::ProxyProtocolConfig* proxy_config = ++ mock_router_filter_.route_entry_.connect_config_->mutable_proxy_protocol_config(); ++ proxy_config->set_version(envoy::config::core::v3::ProxyProtocolConfig::V1); ++ mock_router_filter_.client_connection_.stream_info_.downstream_connection_info_provider_ ++ ->setRemoteAddress(std::make_shared("1.2.3.4", 5)); ++ mock_router_filter_.client_connection_.stream_info_.downstream_connection_info_provider_ ++ ->setLocalAddress(std::make_shared("4.5.6.7", 8)); ++ ++ Buffer::OwnedImpl expected_data; ++ Extensions::Common::ProxyProtocol::generateProxyProtoHeader( ++ *proxy_config, mock_router_filter_.client_connection_, expected_data); ++ ++ // encodeHeaders now results in the proxy proto header being sent. ++ EXPECT_CALL(connection_, write(BufferEqual(&expected_data), false)); ++ EXPECT_TRUE(tcp_upstream_->encodeHeaders(request_, false).ok()); ++ ++ // Data is proxied as usual. ++ EXPECT_CALL(connection_, write(BufferStringEqual("foo"), false)); ++ Buffer::OwnedImpl buffer("foo"); ++ tcp_upstream_->encodeData(buffer, false); ++} ++ ++TEST_F(TcpUpstreamTest, V2Header) { ++ envoy::config::core::v3::ProxyProtocolConfig* proxy_config = ++ mock_router_filter_.route_entry_.connect_config_->mutable_proxy_protocol_config(); ++ proxy_config->set_version(envoy::config::core::v3::ProxyProtocolConfig::V2); ++ mock_router_filter_.client_connection_.stream_info_.downstream_connection_info_provider_ ++ ->setRemoteAddress(std::make_shared("1.2.3.4", 5)); ++ mock_router_filter_.client_connection_.stream_info_.downstream_connection_info_provider_ ++ ->setLocalAddress(std::make_shared("4.5.6.7", 8)); ++ ++ Buffer::OwnedImpl expected_data; ++ Extensions::Common::ProxyProtocol::generateProxyProtoHeader( ++ *proxy_config, mock_router_filter_.client_connection_, expected_data); ++ ++ // encodeHeaders now results in the proxy proto header being sent. ++ EXPECT_CALL(connection_, write(BufferEqual(&expected_data), false)); ++ EXPECT_TRUE(tcp_upstream_->encodeHeaders(request_, false).ok()); ++ ++ // Data is proxied as usual. ++ EXPECT_CALL(connection_, write(BufferStringEqual("foo"), false)); ++ Buffer::OwnedImpl buffer("foo"); ++ tcp_upstream_->encodeData(buffer, false); ++} ++ ++TEST_F(TcpUpstreamTest, TrailersEndStream) { ++ // Swallow the headers. ++ EXPECT_TRUE(tcp_upstream_->encodeHeaders(request_, false).ok()); ++ ++ EXPECT_CALL(connection_, write(BufferStringEqual(""), true)); ++ Envoy::Http::TestRequestTrailerMapImpl trailers{{"foo", "bar"}}; ++ tcp_upstream_->encodeTrailers(trailers); ++} ++ ++TEST_F(TcpUpstreamTest, HeaderEndStreamHalfClose) { ++ EXPECT_CALL(connection_, write(BufferStringEqual(""), true)); ++ EXPECT_TRUE(tcp_upstream_->encodeHeaders(request_, true).ok()); ++} ++ ++TEST_F(TcpUpstreamTest, ReadDisable) { ++ EXPECT_CALL(connection_, readDisable(true)); ++ tcp_upstream_->readDisable(true); ++ ++ EXPECT_CALL(connection_, readDisable(false)); ++ tcp_upstream_->readDisable(false); ++ ++ // Once the connection is closed, don't touch it. ++ connection_.state_ = Network::Connection::State::Closed; ++ EXPECT_CALL(connection_, readDisable(_)).Times(0); ++ tcp_upstream_->readDisable(true); ++} ++ ++TEST_F(TcpUpstreamTest, UpstreamEvent) { ++ // Make sure upstream disconnects result in stream reset. ++ EXPECT_CALL(mock_router_filter_, ++ onUpstreamReset(Envoy::Http::StreamResetReason::ConnectionTermination, "", _)); ++ tcp_upstream_->onEvent(Network::ConnectionEvent::RemoteClose); ++} ++ ++TEST_F(TcpUpstreamTest, Watermarks) { ++ EXPECT_CALL(mock_router_filter_, callbacks()).Times(AnyNumber()); ++ EXPECT_CALL(mock_router_filter_.callbacks_, onDecoderFilterAboveWriteBufferHighWatermark()); ++ tcp_upstream_->onAboveWriteBufferHighWatermark(); ++ ++ EXPECT_CALL(mock_router_filter_.callbacks_, onDecoderFilterBelowWriteBufferLowWatermark()); ++ tcp_upstream_->onBelowWriteBufferLowWatermark(); ++} ++ ++TEST_F(TcpUpstreamTest, EmptyConnectConfig) { ++ NiceMock route_entry; ++ EXPECT_FALSE(route_entry.connect_config_.has_value()); ++ EXPECT_CALL(mock_router_filter_, routeEntry()).WillOnce(Return(&route_entry)); ++ ++ // Swallow the request headers and generate response headers. ++ EXPECT_CALL(connection_, write(_, false)).Times(0); ++ EXPECT_CALL(mock_router_filter_, onUpstreamHeaders(200, _, _, false)); ++ EXPECT_TRUE(tcp_upstream_->encodeHeaders(request_, false).ok()); ++ ++ // Proxy the data. ++ EXPECT_CALL(connection_, write(BufferStringEqual("foo"), false)); ++ Buffer::OwnedImpl buffer("foo"); ++ tcp_upstream_->encodeData(buffer, false); ++ ++ // Metadata is swallowed. ++ Envoy::Http::MetadataMapVector metadata_map_vector; ++ tcp_upstream_->encodeMetadata(metadata_map_vector); ++ ++ // Forward data. ++ Buffer::OwnedImpl response1("bar"); ++ // The dubbo forces end_stream to be true in the onupStreamData function. ++ EXPECT_CALL(mock_router_filter_, onUpstreamData(BufferStringEqual("bar"), _, true)); ++ tcp_upstream_->onUpstreamData(response1, false); ++} ++ ++TEST_F(TcpUpstreamTest, ConnectConfig) { ++ NiceMock route_entry; ++ route_entry.connect_config_ = absl::make_optional(); ++ EXPECT_TRUE(route_entry.connect_config_.has_value()); ++ EXPECT_CALL(mock_router_filter_, routeEntry()).WillOnce(Return(&route_entry)); ++ ++ // Swallow the request headers and generate response headers. ++ EXPECT_CALL(connection_, write(_, false)).Times(0); ++ EXPECT_CALL(mock_router_filter_, onUpstreamHeaders(200, _, _, false)); ++ EXPECT_TRUE(tcp_upstream_->encodeHeaders(request_, false).ok()); ++ ++ // Proxy the data. ++ EXPECT_CALL(connection_, write(BufferStringEqual("foo"), false)); ++ Buffer::OwnedImpl buffer("foo"); ++ tcp_upstream_->encodeData(buffer, false); ++} ++ ++} // namespace DubboTcp ++} // namespace Http ++} // namespace Upstreams ++} // namespace Extensions ++} // namespace Envoy +diff --git a/envoy/config/extension_config_provider.h b/envoy/config/extension_config_provider.h +index ce84225eb6..ba8761f045 100644 +--- a/envoy/config/extension_config_provider.h ++++ b/envoy/config/extension_config_provider.h +@@ -16,7 +16,7 @@ using ConfigAppliedCb = std::function; + * the extension configuration discovery service. Dynamically updated extension + * configurations may share subscriptions across extension config providers. + */ +-template class ExtensionConfigProvider { ++template class ExtensionConfigProvider { + public: + virtual ~ExtensionConfigProvider() = default; + +@@ -35,17 +35,20 @@ public: + virtual absl::optional config() PURE; + }; + +-template class DynamicExtensionConfigProviderBase { ++class DynamicExtensionConfigProviderBase { + public: + virtual ~DynamicExtensionConfigProviderBase() = default; + + /** +- * Update the provider with a new configuration. +- * @param config is an extension factory callback to replace the existing configuration. ++ * Update the provider with a new configuration. This interface accepts proto rather than a ++ * factory callback so that it can be generic over factory types. If instantiating the factory ++ * throws, it should only do so on the main thread, before any changes are applied to workers. ++ * @param config is the new configuration. It is expected that the configuration has already been ++ * validated. + * @param version_info is the version of the new extension configuration. + * @param cb the continuation callback for a completed configuration application on all threads. + */ +- virtual void onConfigUpdate(FactoryCallback config, const std::string& version_info, ++ virtual void onConfigUpdate(const Protobuf::Message& config, const std::string& version_info, + ConfigAppliedCb applied_on_all_threads) PURE; + + /** +@@ -60,9 +63,9 @@ public: + virtual void applyDefaultConfiguration() PURE; + }; + +-template +-class DynamicExtensionConfigProvider : public DynamicExtensionConfigProviderBase, +- public ExtensionConfigProvider {}; ++template ++class DynamicExtensionConfigProvider : public DynamicExtensionConfigProviderBase, ++ public ExtensionConfigProvider {}; + + } // namespace Config + } // namespace Envoy +diff --git a/envoy/filter/config_provider_manager.h b/envoy/filter/config_provider_manager.h +index 824c36e73d..cd1affc579 100644 +--- a/envoy/filter/config_provider_manager.h ++++ b/envoy/filter/config_provider_manager.h +@@ -2,7 +2,6 @@ + + #include "envoy/config/core/v3/config_source.pb.h" + #include "envoy/config/extension_config_provider.h" +-#include "envoy/http/filter.h" + #include "envoy/init/manager.h" + #include "envoy/server/filter_config.h" + +@@ -11,19 +10,20 @@ + namespace Envoy { + namespace Filter { + +-using FilterConfigProvider = +- Envoy::Config::ExtensionConfigProvider; +-using FilterConfigProviderPtr = std::unique_ptr; +-using DynamicFilterConfigProvider = Envoy::Config::DynamicExtensionConfigProvider< +- Server::Configuration::NamedHttpFilterConfigFactory, Envoy::Http::FilterFactoryCb>; +-using DynamicFilterConfigProviderPtr = std::unique_ptr; ++template ++using FilterConfigProvider = Envoy::Config::ExtensionConfigProvider; ++template ++using FilterConfigProviderPtr = std::unique_ptr>; ++template ++using DynamicFilterConfigProvider = Envoy::Config::DynamicExtensionConfigProvider; ++template ++using DynamicFilterConfigProviderPtr = std::unique_ptr>; + + /** + * The FilterConfigProviderManager exposes the ability to get an FilterConfigProvider + * for both static and dynamic filter config providers. + */ +-class FilterConfigProviderManager { ++template class FilterConfigProviderManager { + public: + virtual ~FilterConfigProviderManager() = default; + +@@ -38,7 +38,7 @@ public: + * configured chain + * @param filter_chain_type is the filter chain type + */ +- virtual DynamicFilterConfigProviderPtr createDynamicFilterConfigProvider( ++ virtual DynamicFilterConfigProviderPtr createDynamicFilterConfigProvider( + const envoy::config::core::v3::ExtensionConfigSource& config_source, + const std::string& filter_config_name, Server::Configuration::FactoryContext& factory_context, + const std::string& stat_prefix, bool last_filter_in_filter_chain, +@@ -49,8 +49,8 @@ public: + * @param config is a fully resolved filter instantiation factory. + * @param filter_config_name is the name of the filter configuration resource. + */ +- virtual FilterConfigProviderPtr +- createStaticFilterConfigProvider(const Envoy::Http::FilterFactoryCb& config, ++ virtual FilterConfigProviderPtr ++ createStaticFilterConfigProvider(const FactoryCb& config, + const std::string& filter_config_name) PURE; + }; + +diff --git a/envoy/http/header_map.h b/envoy/http/header_map.h +index 3fb5506c84..d84d7dc516 100644 +--- a/envoy/http/header_map.h ++++ b/envoy/http/header_map.h +@@ -74,7 +74,6 @@ public: + bool operator==(const LowerCaseString& rhs) const { return string_ == rhs.string_; } + bool operator!=(const LowerCaseString& rhs) const { return string_ != rhs.string_; } + bool operator<(const LowerCaseString& rhs) const { return string_.compare(rhs.string_) < 0; } +- + friend std::ostream& operator<<(std::ostream& os, const LowerCaseString& lower_case_string) { + return os << lower_case_string.string_; + } +@@ -82,7 +81,14 @@ public: + // Implicit conversion to absl::string_view. + operator absl::string_view() const { return string_; } + ++#if defined(ALIMESH) ++ virtual ~LowerCaseString() = default; ++ ++protected: ++#else + private: ++#endif ++ + void lower() { + std::transform(string_.begin(), string_.end(), string_.begin(), absl::ascii_tolower); + } +@@ -304,6 +310,7 @@ private: + HEADER_FUNC(Expect) \ + HEADER_FUNC(ForwardedClientCert) \ + HEADER_FUNC(ForwardedFor) \ ++ HEADER_FUNC(ForwardedHost) \ + HEADER_FUNC(ForwardedProto) \ + HEADER_FUNC(GrpcTimeout) \ + HEADER_FUNC(Host) \ +@@ -346,9 +353,6 @@ private: + INLINE_RESP_STRING_HEADERS(HEADER_FUNC) \ + INLINE_RESP_NUMERIC_HEADERS(HEADER_FUNC) + +-/** +- * Default O(1) request and response headers. +- */ + #define INLINE_REQ_RESP_STRING_HEADERS(HEADER_FUNC) \ + HEADER_FUNC(Connection) \ + HEADER_FUNC(ContentType) \ +diff --git a/envoy/router/BUILD b/envoy/router/BUILD +index 86bc52bc99..97fb35e916 100644 +--- a/envoy/router/BUILD ++++ b/envoy/router/BUILD +@@ -11,6 +11,9 @@ envoy_package() + envoy_cc_library( + name = "context_interface", + hdrs = ["context.h"], ++ deps = [ ++ ":router_interface", ++ ], + ) + + envoy_cc_library( +@@ -57,6 +60,9 @@ envoy_cc_library( + envoy_cc_library( + name = "router_interface", + hdrs = ["router.h"], ++ alimesh_deps = [ ++ "//contrib/envoy/http:active_redirect_policy_interface", ++ ], + external_deps = ["abseil_optional"], + deps = [ + ":internal_redirect_interface", +@@ -129,3 +135,13 @@ envoy_cc_library( + "//source/common/common:minimal_logger_lib", + ], + ) ++ ++envoy_cc_library( ++ name = "cluster_specifier_plugin_interface", ++ hdrs = ["cluster_specifier_plugin.h"], ++ deps = [ ++ ":router_interface", ++ "//envoy/config:typed_config_interface", ++ "//envoy/server:factory_context_interface", ++ ], ++) +diff --git a/envoy/router/cluster_specifier_plugin.h b/envoy/router/cluster_specifier_plugin.h +new file mode 100644 +index 0000000000..7e0257aabf +--- /dev/null ++++ b/envoy/router/cluster_specifier_plugin.h +@@ -0,0 +1,57 @@ ++#pragma once ++ ++#include ++#include ++#include ++ ++#include "envoy/common/pure.h" ++#include "envoy/config/typed_config.h" ++#include "envoy/router/router.h" ++#include "envoy/server/factory_context.h" ++ ++namespace Envoy { ++namespace Router { ++ ++/** ++ * Interface class for creating cluster specifier plugin from related route entry. ++ */ ++class ClusterSpecifierPlugin { ++public: ++ virtual ~ClusterSpecifierPlugin() = default; ++ ++ /** ++ * Create route from related route entry and request headers. ++ * ++ * @param parent related route entry. ++ * @param header request headers. ++ * @return RouteConstSharedPtr final route with specific cluster. ++ */ ++ virtual RouteConstSharedPtr route(const RouteEntry& parent, ++ const Http::RequestHeaderMap& header) const PURE; ++}; ++ ++using ClusterSpecifierPluginSharedPtr = std::shared_ptr; ++ ++/* ++ * Extension configuration for cluster specifier plugin factory. ++ */ ++class ClusterSpecifierPluginFactoryConfig : public Envoy::Config::TypedFactory { ++public: ++ /** ++ * Creates a particular cluster specifier plugin factory implementation. ++ * ++ * @param config supplies the configuration for the cluster specifier plugin factory extension. ++ * @return ClusterSpecifierPluginSharedPtr cluster specifier plugin use to create final route from ++ * request headers. ++ */ ++ virtual ClusterSpecifierPluginSharedPtr ++ createClusterSpecifierPlugin(const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext& context) PURE; ++ ++ std::string category() const override { return "envoy.router.cluster_specifier_plugin"; } ++}; ++ ++using ClusterSpecifierPluginFactoryConfigPtr = std::unique_ptr; ++ ++} // namespace Router ++} // namespace Envoy +diff --git a/envoy/router/context.h b/envoy/router/context.h +index 2d3dc4ad92..54fdbdfb74 100644 +--- a/envoy/router/context.h ++++ b/envoy/router/context.h +@@ -1,12 +1,14 @@ + #pragma once + + #include "envoy/common/pure.h" ++#include "envoy/router/router.h" + + namespace Envoy { + namespace Router { + + struct StatNames; + struct VirtualClusterStatNames; ++struct RouteStatNames; + + class Context { + public: +@@ -21,6 +23,16 @@ public: + * @return a struct containing StatNames for virtual cluster stats. + */ + virtual const VirtualClusterStatNames& virtualClusterStatNames() const PURE; ++ ++ /** ++ * @return a struct containing StatNames for route level stats. ++ */ ++ virtual const RouteStatNames& routeStatNames() const PURE; ++ ++ /** ++ * @return a reference to the default generic connection pool factory. ++ */ ++ virtual GenericConnPoolFactory& genericConnPoolFactory() PURE; + }; + + } // namespace Router +diff --git a/envoy/router/router.h b/envoy/router/router.h +index b7d8f8db2f..ad2e5bfd74 100644 +--- a/envoy/router/router.h ++++ b/envoy/router/router.h +@@ -30,6 +30,10 @@ + + #include "absl/types/optional.h" + ++#if defined(ALIMESH) ++#include "contrib/envoy/http/active_redirect_policy.h" ++#endif ++ + namespace Envoy { + + namespace Upstream { +@@ -487,12 +491,58 @@ using ShadowPolicyPtr = std::unique_ptr; + STATNAME(vcluster) \ + STATNAME(vhost) + ++/** ++ * All route level stats. @see stats_macro.h ++ */ ++#define ALL_ROUTE_STATS(COUNTER, GAUGE, HISTOGRAM, TEXT_READOUT, STATNAME) \ ++ COUNTER(upstream_rq_retry) \ ++ COUNTER(upstream_rq_retry_limit_exceeded) \ ++ COUNTER(upstream_rq_retry_overflow) \ ++ COUNTER(upstream_rq_retry_success) \ ++ COUNTER(upstream_rq_timeout) \ ++ COUNTER(upstream_rq_total) \ ++ STATNAME(route) \ ++ STATNAME(vhost) ++ + /** + * Struct definition for all virtual cluster stats. @see stats_macro.h + */ + MAKE_STAT_NAMES_STRUCT(VirtualClusterStatNames, ALL_VIRTUAL_CLUSTER_STATS); + MAKE_STATS_STRUCT(VirtualClusterStats, VirtualClusterStatNames, ALL_VIRTUAL_CLUSTER_STATS); + ++/** ++ * Struct definition for all route level stats. @see stats_macro.h ++ */ ++MAKE_STAT_NAMES_STRUCT(RouteStatNames, ALL_ROUTE_STATS); ++MAKE_STATS_STRUCT(RouteStats, RouteStatNames, ALL_ROUTE_STATS); ++ ++/** ++ * RouteStatsContext defines config needed to generate all route level stats. ++ */ ++class RouteStatsContext { ++public: ++ RouteStatsContext(Stats::Scope& scope, const RouteStatNames& route_stat_names, ++ const Stats::StatName& vhost_stat_name, const std::string& stat_prefix) ++ : route_stat_name_storage_(stat_prefix, scope.symbolTable()), ++ route_stats_scope_(Stats::Utility::scopeFromStatNames( ++ scope, {route_stat_names.vhost_, vhost_stat_name, route_stat_names.route_, ++ route_stat_name_storage_.statName()})), ++ route_stat_name_(route_stat_name_storage_.statName()), ++ route_stats_(route_stat_names, *route_stats_scope_) {} ++ ++ const Stats::StatName statName() const { return route_stat_name_; } ++ const RouteStats& stats() const { return route_stats_; } ++ ++private: ++ const Stats::StatNameManagedStorage route_stat_name_storage_; ++ Stats::ScopeSharedPtr route_stats_scope_; ++ Stats::StatName route_stat_name_; ++ RouteStats route_stats_; ++}; ++ ++using RouteStatsContextPtr = std::unique_ptr; ++using RouteStatsContextOptRef = OptRef; ++ + /** + * Virtual cluster definition (allows splitting a virtual host into virtual clusters orthogonal to + * routes for stat tracking and priority purposes). +@@ -501,6 +551,11 @@ class VirtualCluster { + public: + virtual ~VirtualCluster() = default; + ++ /** ++ * @return the string name of the virtual cluster. ++ */ ++ virtual const absl::optional& name() const PURE; ++ + /** + * @return the stat-name of the virtual cluster. + */ +@@ -870,6 +925,11 @@ public: + */ + virtual bool autoHostRewrite() const PURE; + ++ /** ++ * @return bool true if the x-forwarded-host header should be updated. ++ */ ++ virtual bool appendXfh() const PURE; ++ + /** + * @return MetadataMatchCriteria* the metadata that a subset load balancer should match when + * selecting an upstream host +@@ -928,6 +988,15 @@ public: + * @return std::string& the name of the route. + */ + virtual const std::string& routeName() const PURE; ++ ++#if defined(ALIMESH) ++ virtual const InternalActiveRedirectPolicy& internalActiveRedirectPolicy() const PURE; ++#endif ++ /** ++ * @return RouteStatsContextOptRef the config needed to generate route level stats. ++ */ ++ virtual const RouteStatsContextOptRef routeStatsContext() const PURE; ++ + }; + + /** +@@ -1206,9 +1275,9 @@ public: + class UpstreamToDownstream : public Http::ResponseDecoder, public Http::StreamCallbacks { + public: + /** +- * @return return the routeEntry for the downstream stream. ++ * @return return the route for the downstream stream. + */ +- virtual const RouteEntry& routeEntry() const PURE; ++ virtual const Route& route() const PURE; + /** + * @return return the connection for the downstream stream. + */ +diff --git a/envoy/stream_info/stream_info.h b/envoy/stream_info/stream_info.h +index 1a48d18e2c..c6d82db4f4 100644 +--- a/envoy/stream_info/stream_info.h ++++ b/envoy/stream_info/stream_info.h +@@ -290,6 +290,16 @@ public: + * @return std::string& the name of the route. + */ + virtual const std::string& getRouteName() const PURE; ++ /** ++ * @param std::string name denotes the name of the virtual cluster. ++ */ ++ virtual void setVirtualClusterName(const absl::optional& name) PURE; ++ ++ /** ++ * @return std::string& the name of the virtual cluster which got matched. ++ */ ++ virtual const absl::optional& virtualClusterName() const PURE; ++ + /** + * @param bytes_received denotes number of bytes to add to total received bytes. + */ +diff --git a/envoy/thread_local/thread_local.h b/envoy/thread_local/thread_local.h +index b314fa817a..07f1e03e82 100644 +--- a/envoy/thread_local/thread_local.h ++++ b/envoy/thread_local/thread_local.h +@@ -77,6 +77,13 @@ protected: + // Callers must use the TypedSlot API, below. + virtual void runOnAllThreads(const UpdateCb& update_cb) PURE; + virtual void runOnAllThreads(const UpdateCb& update_cb, const Event::PostCb& complete_cb) PURE; ++ ++ /** ++ * Returns whether or not global threading has been shutdown. ++ * ++ * @return true if global threading has been shutdown or false if not. ++ */ ++ virtual bool isShutdown() const PURE; + }; + + using SlotPtr = std::unique_ptr; +@@ -177,6 +184,13 @@ public: + slot_->runOnAllThreads(makeSlotUpdateCb(cb), complete_cb); + } + ++ /** ++ * Returns whether or not global threading has been shutdown. ++ * ++ * @return true if global threading has been shutdown or false if not. ++ */ ++ bool isShutdown() const { return slot_->isShutdown(); }; ++ + private: + static OptRef getOpt(ThreadLocalObjectSharedPtr obj) { + if (obj) { +diff --git a/envoy/upstream/outlier_detection.h b/envoy/upstream/outlier_detection.h +index 038e81b88e..aefd450cac 100644 +--- a/envoy/upstream/outlier_detection.h ++++ b/envoy/upstream/outlier_detection.h +@@ -110,6 +110,10 @@ public: + * and LocalOrigin type returns success rate for local origin errors. + */ + virtual double successRate(SuccessRateMonitorType type) const PURE; ++ ++#if defined(ALIMESH) ++ virtual void forceEjectHost() PURE; ++#endif + }; + + using DetectorHostMonitorPtr = std::unique_ptr; +diff --git a/source/common/config/well_known_names.cc b/source/common/config/well_known_names.cc +index 71a03839b1..2f186e5b47 100644 +--- a/source/common/config/well_known_names.cc ++++ b/source/common/config/well_known_names.cc +@@ -136,6 +136,9 @@ TagNameValues::TagNameValues() { + + // listener_manager.(worker_.)* + addRe2(WORKER_ID, R"(^listener_manager\.((worker_\d+)\.))", "listener_manager.worker_"); ++ ++ // vhost.[.]route.(.)* ++ addTokenized(ROUTE, "vhost.*.route.$.**"); + } + + void TagNameValues::addRe2(const std::string& name, const std::string& regex, +diff --git a/source/common/config/well_known_names.h b/source/common/config/well_known_names.h +index 0b694392a4..5c556f682d 100644 +--- a/source/common/config/well_known_names.h ++++ b/source/common/config/well_known_names.h +@@ -126,6 +126,8 @@ public: + const std::string RESPONSE_CODE_CLASS = "envoy.response_code_class"; + // Route config name for RDS updates + const std::string RDS_ROUTE_CONFIG = "envoy.rds_route_config"; ++ // Request route given by the Router http filter ++ const std::string ROUTE = "envoy.route"; + // Listener manager worker id + const std::string WORKER_ID = "envoy.worker_id"; + +diff --git a/source/common/conn_pool/BUILD b/source/common/conn_pool/BUILD +index d526dfbf95..048aa131fb 100644 +--- a/source/common/conn_pool/BUILD ++++ b/source/common/conn_pool/BUILD +@@ -14,6 +14,7 @@ envoy_cc_library( + hdrs = ["conn_pool_base.h"], + deps = [ + "//envoy/stats:timespan_interface", ++ "//source/common/common:debug_recursion_checker_lib", + "//source/common/common:linked_object", + "//source/common/stats:timespan_lib", + "//source/common/upstream:upstream_lib", +diff --git a/source/common/conn_pool/conn_pool_base.cc b/source/common/conn_pool/conn_pool_base.cc +index 113836ab13..a0f6d30ba5 100644 +--- a/source/common/conn_pool/conn_pool_base.cc ++++ b/source/common/conn_pool/conn_pool_base.cc +@@ -1,6 +1,7 @@ + #include "source/common/conn_pool/conn_pool_base.h" + + #include "source/common/common/assert.h" ++#include "source/common/common/debug_recursion_checker.h" + #include "source/common/network/transport_socket_options_impl.h" + #include "source/common/runtime/runtime_features.h" + #include "source/common/stats/timespan_impl.h" +@@ -333,6 +334,8 @@ void ConnPoolImplBase::transitionActiveClientState(ActiveClient& client, + void ConnPoolImplBase::addIdleCallbackImpl(Instance::IdleCb cb) { idle_callbacks_.push_back(cb); } + + void ConnPoolImplBase::closeIdleConnectionsForDrainingPool() { ++ Common::AutoDebugRecursionChecker assert_not_in(recursion_checker_); ++ + // Create a separate list of elements to close to avoid mutate-while-iterating problems. + std::list to_close; + +@@ -387,11 +390,7 @@ bool ConnPoolImplBase::isIdleImpl() const { + connecting_clients_.empty(); + } + +-void ConnPoolImplBase::checkForIdleAndCloseIdleConnsIfDraining() { +- if (is_draining_for_deletion_) { +- closeIdleConnectionsForDrainingPool(); +- } +- ++void ConnPoolImplBase::checkForIdleAndNotify() { + if (isIdleImpl()) { + ENVOY_LOG(debug, "invoking idle callbacks - is_draining_for_deletion_={}", + is_draining_for_deletion_); +@@ -401,6 +400,14 @@ void ConnPoolImplBase::checkForIdleAndCloseIdleConnsIfDraining() { + } + } + ++void ConnPoolImplBase::checkForIdleAndCloseIdleConnsIfDraining() { ++ if (is_draining_for_deletion_) { ++ closeIdleConnectionsForDrainingPool(); ++ } ++ ++ checkForIdleAndNotify(); ++} ++ + void ConnPoolImplBase::onConnectionEvent(ActiveClient& client, absl::string_view failure_reason, + Network::ConnectionEvent event) { + if (client.state() == ActiveClient::State::CONNECTING) { +@@ -459,7 +466,15 @@ void ConnPoolImplBase::onConnectionEvent(ActiveClient& client, absl::string_view + + dispatcher_.deferredDelete(client.removeFromList(owningList(client.state()))); + +- checkForIdleAndCloseIdleConnsIfDraining(); ++ // Check if the pool transitioned to idle state after removing closed client ++ // from one of the client tracking lists. ++ // There is no need to check if other connections are idle in a draining pool ++ // because the pool will close all idle connection when it is starting to ++ // drain. ++ // Trying to close other connections here can lead to deep recursion when ++ // a large number idle connections are closed at the start of pool drain. ++ // See CdsIntegrationTest.CdsClusterDownWithLotsOfIdleConnections for an example. ++ checkForIdleAndNotify(); + + client.setState(ActiveClient::State::CLOSED); + +diff --git a/source/common/conn_pool/conn_pool_base.h b/source/common/conn_pool/conn_pool_base.h +index dafc845f88..b8884ddee7 100644 +--- a/source/common/conn_pool/conn_pool_base.h ++++ b/source/common/conn_pool/conn_pool_base.h +@@ -6,6 +6,7 @@ + #include "envoy/stats/timespan.h" + #include "envoy/upstream/cluster_manager.h" + ++#include "source/common/common/debug_recursion_checker.h" + #include "source/common/common/dump_state_utils.h" + #include "source/common/common/linked_object.h" + +@@ -201,6 +202,9 @@ public: + void onConnectionEvent(ActiveClient& client, absl::string_view failure_reason, + Network::ConnectionEvent event); + ++ // Check if the pool has gone idle and invoke idle notification callbacks. ++ void checkForIdleAndNotify(); ++ + // See if the pool has gone idle. If we're draining, this will also close idle connections. + void checkForIdleAndCloseIdleConnsIfDraining(); + +@@ -341,6 +345,7 @@ private: + + void onUpstreamReady(); + Event::SchedulableCallbackPtr upstream_ready_cb_; ++ Common::DebugRecursionChecker recursion_checker_; + }; + + } // namespace ConnectionPool +diff --git a/source/common/filter/config_discovery_impl.cc b/source/common/filter/config_discovery_impl.cc +index 74acc6b838..840035f4a7 100644 +--- a/source/common/filter/config_discovery_impl.cc ++++ b/source/common/filter/config_discovery_impl.cc +@@ -8,7 +8,6 @@ + + #include "source/common/common/containers.h" + #include "source/common/common/thread.h" +-#include "source/common/config/utility.h" + #include "source/common/grpc/common.h" + #include "source/common/protobuf/utility.h" + +@@ -57,23 +56,15 @@ void DynamicFilterConfigProviderImplBase::validateTypeUrl(const std::string& typ + + const std::string& DynamicFilterConfigProviderImplBase::name() { return subscription_->name(); } + +-void DynamicFilterConfigProviderImplBase::validateTerminalFilter(const std::string& name, +- const std::string& filter_type, +- bool is_terminal_filter) { +- Config::Utility::validateTerminalFilters(name, filter_type, filter_chain_type_, +- is_terminal_filter, last_filter_in_filter_chain_); +-} +- + FilterConfigSubscription::FilterConfigSubscription( + const envoy::config::core::v3::ConfigSource& config_source, +- const std::string& filter_config_name, Server::Configuration::FactoryContext& factory_context, +- const std::string& stat_prefix, ++ const std::string& filter_config_name, ++ Server::Configuration::ServerFactoryContext& factory_context, const std::string& stat_prefix, + FilterConfigProviderManagerImplBase& filter_config_provider_manager, + const std::string& subscription_id) + : Config::SubscriptionBase( + factory_context.messageValidationContext().dynamicValidationVisitor(), "name"), + filter_config_name_(filter_config_name), factory_context_(factory_context), +- validator_(factory_context.messageValidationContext().dynamicValidationVisitor()), + init_target_(fmt::format("FilterConfigSubscription init {}", filter_config_name_), + [this]() { start(); }), + scope_(factory_context.scope().createScope(stat_prefix + "extension_config_discovery." + +@@ -116,9 +107,6 @@ void FilterConfigSubscription::onConfigUpdate( + if (new_hash == last_config_hash_) { + return; + } +- auto& factory = +- Config::Utility::getAndCheckFactory( +- filter_config); + // Ensure that the filter config is valid in the filter chain context once the proto is processed. + // Validation happens before updating to prevent a partial update application. It might be + // possible that the providers have distinct type URL constraints. +@@ -126,29 +114,25 @@ void FilterConfigSubscription::onConfigUpdate( + for (auto* provider : filter_config_providers_) { + provider->validateTypeUrl(type_url); + } +- ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig( +- filter_config.typed_config(), validator_, factory); +- bool is_terminal_filter = factory.isTerminalFilterByProto(*message, factory_context_); ++ auto [message, factory_name] = ++ filter_config_provider_manager_.getMessage(filter_config, factory_context_); + for (auto* provider : filter_config_providers_) { +- provider->validateTerminalFilter(filter_config_name_, factory.name(), is_terminal_filter); ++ provider->validateMessage(filter_config_name_, *message, factory_name); + } +- Envoy::Http::FilterFactoryCb factory_callback = +- factory.createFilterFactoryFromProto(*message, stat_prefix_, factory_context_); + ENVOY_LOG(debug, "Updating filter config {}", filter_config_name_); + + Common::applyToAllWithCleanup( + filter_config_providers_, +- [&factory_callback, &version_info](DynamicFilterConfigProviderImplBase* provider, +- std::shared_ptr cleanup) { +- provider->onConfigUpdate(factory_callback, version_info, [cleanup] {}); ++ [&message = message, &version_info](DynamicFilterConfigProviderImplBase* provider, ++ std::shared_ptr cleanup) { ++ provider->onConfigUpdate(*message, version_info, [cleanup] {}); + }, + [this]() { stats_.config_reload_.inc(); }); + last_config_hash_ = new_hash; +- last_config_ = factory_callback; ++ last_config_ = std::move(message); + last_type_url_ = type_url; + last_version_info_ = version_info; +- last_filter_name_ = factory.name(); +- last_filter_is_terminal_ = is_terminal_filter; ++ last_factory_name_ = factory_name; + } + + void FilterConfigSubscription::onConfigUpdate( +@@ -165,10 +149,10 @@ void FilterConfigSubscription::onConfigUpdate( + [this]() { stats_.config_reload_.inc(); }); + + last_config_hash_ = 0; +- last_config_ = absl::nullopt; ++ last_config_ = nullptr; + last_type_url_ = ""; +- last_filter_is_terminal_ = false; +- last_filter_name_ = ""; ++ last_version_info_ = ""; ++ last_factory_name_ = ""; + } else if (!added_resources.empty()) { + onConfigUpdate(added_resources, added_resources[0].get().version()); + } +@@ -202,7 +186,8 @@ std::shared_ptr FilterConfigProviderManagerImplBase::g + auto it = subscriptions_.find(subscription_id); + if (it == subscriptions_.end()) { + auto subscription = std::make_shared( +- config_source, name, factory_context, stat_prefix, *this, subscription_id); ++ config_source, name, factory_context.getServerFactoryContext(), stat_prefix, *this, ++ subscription_id); + subscriptions_.insert({subscription_id, std::weak_ptr(subscription)}); + return subscription; + } else { +@@ -222,11 +207,11 @@ void FilterConfigProviderManagerImplBase::applyLastOrDefaultConfig( + // update arrives first. In this case, use the default config, increment a metric, + // and the applied config eventually converges once ECDS update arrives. + bool last_config_valid = false; +- if (subscription->lastConfig().has_value()) { ++ if (subscription->lastConfig()) { + TRY_ASSERT_MAIN_THREAD { + provider.validateTypeUrl(subscription->lastTypeUrl()); +- provider.validateTerminalFilter(filter_config_name, subscription->lastFilterName(), +- subscription->isLastFilterTerminal()); ++ provider.validateMessage(filter_config_name, *subscription->lastConfig(), ++ subscription->lastFactoryName()); + last_config_valid = true; + } + END_TRY catch (const EnvoyException& e) { +@@ -235,7 +220,7 @@ void FilterConfigProviderManagerImplBase::applyLastOrDefaultConfig( + subscription->incrementConflictCounter(); + } + if (last_config_valid) { +- provider.onConfigUpdate(subscription->lastConfig().value(), subscription->lastVersionInfo(), ++ provider.onConfigUpdate(*subscription->lastConfig(), subscription->lastVersionInfo(), + nullptr); + } + } +@@ -246,49 +231,23 @@ void FilterConfigProviderManagerImplBase::applyLastOrDefaultConfig( + } + } + +-DynamicFilterConfigProviderPtr FilterConfigProviderManagerImpl::createDynamicFilterConfigProvider( +- const envoy::config::core::v3::ExtensionConfigSource& config_source, +- const std::string& filter_config_name, Server::Configuration::FactoryContext& factory_context, +- const std::string& stat_prefix, bool last_filter_in_filter_chain, +- const std::string& filter_chain_type) { +- auto subscription = getSubscription(config_source.config_source(), filter_config_name, +- factory_context, stat_prefix); +- // For warming, wait until the subscription receives the first response to indicate readiness. +- // Otherwise, mark ready immediately and start the subscription on initialization. A default +- // config is expected in the latter case. +- if (!config_source.apply_default_config_without_warming()) { +- factory_context.initManager().add(subscription->initTarget()); +- } +- absl::flat_hash_set require_type_urls; +- for (const auto& type_url : config_source.type_urls()) { +- auto factory_type_url = TypeUtil::typeUrlToDescriptorFullName(type_url); +- require_type_urls.emplace(factory_type_url); +- } +- +- Envoy::Http::FilterFactoryCb default_config = nullptr; +- if (config_source.has_default_config()) { +- default_config = getDefaultConfig(config_source.default_config(), filter_config_name, +- factory_context, stat_prefix, last_filter_in_filter_chain, +- filter_chain_type, require_type_urls); +- } +- +- auto provider = std::make_unique( +- subscription, require_type_urls, factory_context, default_config, last_filter_in_filter_chain, +- filter_chain_type); +- +- // Ensure the subscription starts if it has not already. +- if (config_source.apply_default_config_without_warming()) { +- factory_context.initManager().add(provider->initTarget()); +- } +- applyLastOrDefaultConfig(subscription, *provider, filter_config_name); +- return provider; ++std::tuple HttpFilterConfigProviderManagerImpl::getMessage( ++ const envoy::config::core::v3::TypedExtensionConfig& filter_config, ++ Server::Configuration::ServerFactoryContext& factory_context) const { ++ auto& factory = ++ Config::Utility::getAndCheckFactory( ++ filter_config); ++ ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig( ++ filter_config.typed_config(), ++ factory_context.messageValidationContext().dynamicValidationVisitor(), factory); ++ return {std::move(message), factory.name()}; + } + +-Http::FilterFactoryCb HttpFilterConfigProviderManagerImpl::getDefaultConfig( ++ProtobufTypes::MessagePtr HttpFilterConfigProviderManagerImpl::getDefaultConfig( + const ProtobufWkt::Any& proto_config, const std::string& filter_config_name, +- Server::Configuration::FactoryContext& factory_context, const std::string& stat_prefix, +- bool last_filter_in_filter_chain, const std::string& filter_chain_type, +- const absl::flat_hash_set require_type_urls) const { ++ Server::Configuration::FactoryContext& factory_context, bool last_filter_in_filter_chain, ++ const std::string& filter_chain_type, ++ const absl::flat_hash_set& require_type_urls) const { + auto* default_factory = + Config::Utility::getFactoryByType( + proto_config); +@@ -304,7 +263,7 @@ Http::FilterFactoryCb HttpFilterConfigProviderManagerImpl::getDefaultConfig( + filter_config_name, default_factory->name(), filter_chain_type, + default_factory->isTerminalFilterByProto(*message, factory_context), + last_filter_in_filter_chain); +- return default_factory->createFilterFactoryFromProto(*message, stat_prefix, factory_context); ++ return message; + } + + } // namespace Filter +diff --git a/source/common/filter/config_discovery_impl.h b/source/common/filter/config_discovery_impl.h +index 7646f42176..c07ab14a94 100644 +--- a/source/common/filter/config_discovery_impl.h ++++ b/source/common/filter/config_discovery_impl.h +@@ -14,6 +14,7 @@ + + #include "source/common/common/assert.h" + #include "source/common/config/subscription_base.h" ++#include "source/common/config/utility.h" + #include "source/common/init/manager_impl.h" + #include "source/common/init/target_impl.h" + +@@ -31,8 +32,7 @@ using FilterConfigSubscriptionSharedPtr = std::shared_ptr { ++class DynamicFilterConfigProviderImplBase : public Config::DynamicExtensionConfigProviderBase { + public: + DynamicFilterConfigProviderImplBase(FilterConfigSubscriptionSharedPtr& subscription, + const absl::flat_hash_set& require_type_urls, +@@ -43,8 +43,8 @@ public: + const Init::Target& initTarget() const { return init_target_; } + + void validateTypeUrl(const std::string& type_url) const; +- void validateTerminalFilter(const std::string& name, const std::string& filter_type, +- bool is_terminal_filter); ++ virtual void validateMessage(const std::string& config_name, const Protobuf::Message& message, ++ const std::string& factory_name) const PURE; + + const std::string& name(); + +@@ -56,6 +56,7 @@ private: + // case no warming is requested by any other filter config provider. + Init::TargetImpl init_target_; + ++protected: + const bool last_filter_in_filter_chain_; + const std::string filter_chain_type_; + }; +@@ -63,55 +64,60 @@ private: + /** + * Implementation of a filter config provider using discovery subscriptions. + **/ ++template + class DynamicFilterConfigProviderImpl : public DynamicFilterConfigProviderImplBase, +- public DynamicFilterConfigProvider { ++ public DynamicFilterConfigProvider { + public: + DynamicFilterConfigProviderImpl(FilterConfigSubscriptionSharedPtr& subscription, + const absl::flat_hash_set& require_type_urls, + Server::Configuration::FactoryContext& factory_context, +- Envoy::Http::FilterFactoryCb default_config, ++ ProtobufTypes::MessagePtr&& default_config, + bool last_filter_in_filter_chain, +- const std::string& filter_chain_type) ++ const std::string& filter_chain_type, ++ const std::string& stat_prefix) + : DynamicFilterConfigProviderImplBase(subscription, require_type_urls, + last_filter_in_filter_chain, filter_chain_type), +- default_configuration_(default_config ? absl::make_optional(default_config) +- : absl::nullopt), +- tls_(factory_context.threadLocal()) { ++ stat_prefix_(stat_prefix), factory_context_(factory_context), ++ main_config_(std::make_shared()), ++ default_configuration_(std::move(default_config)), tls_(factory_context.threadLocal()) { + tls_.set([](Event::Dispatcher&) { return std::make_shared(); }); + }; + ++ ~DynamicFilterConfigProviderImpl() override { ++ // Issuing an empty update to guarantee that the shared current config is ++ // deleted on the main thread last. This is required if the current config ++ // holds its own TLS. ++ if (!tls_.isShutdown()) { ++ update(absl::nullopt, nullptr); ++ } ++ } ++ ++ // DynamicFilterConfigProviderImplBase ++ void validateMessage(const std::string& config_name, const Protobuf::Message& message, ++ const std::string& factory_name) const override { ++ auto* factory = Registry::FactoryRegistry::getFactory(factory_name); ++ bool is_terminal_filter = factory->isTerminalFilterByProto(message, factory_context_); ++ Config::Utility::validateTerminalFilters(config_name, factory_name, filter_chain_type_, ++ is_terminal_filter, last_filter_in_filter_chain_); ++ } ++ + // Config::ExtensionConfigProvider + const std::string& name() override { return DynamicFilterConfigProviderImplBase::name(); } +- absl::optional config() override { return tls_->config_; } +- +- // Config::DynamicExtensionConfigProvider +- void onConfigUpdate(Envoy::Http::FilterFactoryCb config, const std::string&, +- Config::ConfigAppliedCb cb) override { +- tls_.runOnAllThreads( +- [config, cb](OptRef tls) { +- tls->config_ = config; +- if (cb) { +- cb(); +- } +- }, +- [this, config]() { +- // This happens after all workers have discarded the previous config so it can be safely +- // deleted on the main thread by an update with the new config. +- this->current_config_ = config; +- }); ++ absl::optional config() override { return tls_->config_; } ++ ++ // Config::DynamicExtensionConfigProviderBase ++ void onConfigUpdate(const Protobuf::Message& message, const std::string&, ++ Config::ConfigAppliedCb applied_on_all_threads) override { ++ const FactoryCb config = instantiateFilterFactory(message); ++ update(config, applied_on_all_threads); + } + + void onConfigRemoved(Config::ConfigAppliedCb applied_on_all_threads) override { +- tls_.runOnAllThreads( +- [config = default_configuration_](OptRef tls) { tls->config_ = config; }, +- [this, applied_on_all_threads]() { +- // This happens after all workers have discarded the previous config so it can be safely +- // deleted on the main thread by an update with the new config. +- this->current_config_ = default_configuration_; +- if (applied_on_all_threads) { +- applied_on_all_threads(); +- } +- }); ++ const absl::optional default_config = ++ default_configuration_ ++ ? absl::make_optional(instantiateFilterFactory(*default_configuration_)) ++ : absl::nullopt; ++ update(default_config, applied_on_all_threads); + } + + void applyDefaultConfiguration() override { +@@ -121,15 +127,41 @@ public: + } + + private: ++ FactoryCb instantiateFilterFactory(const Protobuf::Message& message) const { ++ auto* factory = Registry::FactoryRegistry::getFactoryByType(message.GetTypeName()); ++ return factory->createFilterFactoryFromProto(message, stat_prefix_, factory_context_); ++ } ++ ++ void update(absl::optional config, Config::ConfigAppliedCb applied_on_all_threads) { ++ // This call must not capture 'this' as it is invoked on all workers asynchronously. ++ tls_.runOnAllThreads([config](OptRef tls) { tls->config_ = config; }, ++ [main_config = main_config_, config, applied_on_all_threads]() { ++ // This happens after all workers have discarded the previous config so ++ // it can be safely deleted on the main thread by an update with the new ++ // config. ++ main_config->current_config_ = config; ++ if (applied_on_all_threads) { ++ applied_on_all_threads(); ++ } ++ }); ++ } ++ + struct ThreadLocalConfig : public ThreadLocal::ThreadLocalObject { + ThreadLocalConfig() : config_{absl::nullopt} {} +- absl::optional config_{}; ++ absl::optional config_{}; + }; + + // Currently applied configuration to ensure that the main thread deletes the last reference to +- // it. +- absl::optional current_config_{absl::nullopt}; +- const absl::optional default_configuration_; ++ // it. Filter factories may hold their own thread local storage which is required to be deleted ++ // on the main thread. ++ struct MainConfig { ++ absl::optional current_config_{absl::nullopt}; ++ }; ++ ++ const std::string stat_prefix_; ++ Server::Configuration::FactoryContext& factory_context_; ++ std::shared_ptr main_config_; ++ const ProtobufTypes::MessagePtr default_configuration_; + ThreadLocal::TypedSlot tls_; + }; + +@@ -159,7 +191,7 @@ class FilterConfigSubscription + public: + FilterConfigSubscription(const envoy::config::core::v3::ConfigSource& config_source, + const std::string& filter_config_name, +- Server::Configuration::FactoryContext& factory_context, ++ Server::Configuration::ServerFactoryContext& factory_context, + const std::string& stat_prefix, + FilterConfigProviderManagerImplBase& filter_config_provider_manager, + const std::string& subscription_id); +@@ -168,11 +200,10 @@ public: + + const Init::SharedTargetImpl& initTarget() { return init_target_; } + const std::string& name() { return filter_config_name_; } +- const absl::optional& lastConfig() { return last_config_; } ++ const Protobuf::Message* lastConfig() { return last_config_.get(); } + const std::string& lastTypeUrl() { return last_type_url_; } + const std::string& lastVersionInfo() { return last_version_info_; } +- const std::string& lastFilterName() { return last_filter_name_; } +- bool isLastFilterTerminal() { return last_filter_is_terminal_; } ++ const std::string& lastFactoryName() { return last_factory_name_; } + void incrementConflictCounter(); + + private: +@@ -189,13 +220,11 @@ private: + + const std::string filter_config_name_; + uint64_t last_config_hash_{0ul}; +- absl::optional last_config_{absl::nullopt}; ++ ProtobufTypes::MessagePtr last_config_; + std::string last_type_url_; + std::string last_version_info_; +- std::string last_filter_name_; +- bool last_filter_is_terminal_; +- Server::Configuration::FactoryContext& factory_context_; +- ProtobufMessage::ValidationVisitor& validator_; ++ std::string last_factory_name_; ++ Server::Configuration::ServerFactoryContext& factory_context_; + + Init::SharedTargetImpl init_target_; + bool started_{false}; +@@ -218,18 +247,18 @@ private: + /** + * Provider implementation of a static filter config. + **/ +-class StaticFilterConfigProviderImpl : public FilterConfigProvider { ++template ++class StaticFilterConfigProviderImpl : public FilterConfigProvider { + public: +- StaticFilterConfigProviderImpl(const Envoy::Http::FilterFactoryCb& config, +- const std::string filter_config_name) ++ StaticFilterConfigProviderImpl(const FactoryCb& config, const std::string filter_config_name) + : config_(config), filter_config_name_(filter_config_name) {} + + // Config::ExtensionConfigProvider + const std::string& name() override { return filter_config_name_; } +- absl::optional config() override { return config_; } ++ absl::optional config() override { return config_; } + + private: +- Envoy::Http::FilterFactoryCb config_; ++ FactoryCb config_; + const std::string filter_config_name_; + }; + +@@ -237,6 +266,13 @@ private: + * Base class for a FilterConfigProviderManager. + */ + class FilterConfigProviderManagerImplBase : Logger::Loggable { ++public: ++ virtual ~FilterConfigProviderManagerImplBase() = default; ++ ++ virtual std::tuple ++ getMessage(const envoy::config::core::v3::TypedExtensionConfig& filter_config, ++ Server::Configuration::ServerFactoryContext& factory_context) const PURE; ++ + protected: + std::shared_ptr + getSubscription(const envoy::config::core::v3::ConfigSource& config_source, +@@ -254,39 +290,77 @@ private: + /** + * An implementation of FilterConfigProviderManager. + */ ++template + class FilterConfigProviderManagerImpl : public FilterConfigProviderManagerImplBase, +- public FilterConfigProviderManager, ++ public FilterConfigProviderManager, + public Singleton::Instance { + public: +- DynamicFilterConfigProviderPtr createDynamicFilterConfigProvider( ++ DynamicFilterConfigProviderPtr createDynamicFilterConfigProvider( + const envoy::config::core::v3::ExtensionConfigSource& config_source, + const std::string& filter_config_name, Server::Configuration::FactoryContext& factory_context, + const std::string& stat_prefix, bool last_filter_in_filter_chain, +- const std::string& filter_chain_type) override; ++ const std::string& filter_chain_type) override { ++ auto subscription = getSubscription(config_source.config_source(), filter_config_name, ++ factory_context, stat_prefix); ++ // For warming, wait until the subscription receives the first response to indicate readiness. ++ // Otherwise, mark ready immediately and start the subscription on initialization. A default ++ // config is expected in the latter case. ++ if (!config_source.apply_default_config_without_warming()) { ++ factory_context.initManager().add(subscription->initTarget()); ++ } ++ absl::flat_hash_set require_type_urls; ++ for (const auto& type_url : config_source.type_urls()) { ++ auto factory_type_url = TypeUtil::typeUrlToDescriptorFullName(type_url); ++ require_type_urls.emplace(factory_type_url); ++ } ++ ++ ProtobufTypes::MessagePtr default_config; ++ if (config_source.has_default_config()) { ++ default_config = ++ getDefaultConfig(config_source.default_config(), filter_config_name, factory_context, ++ last_filter_in_filter_chain, filter_chain_type, require_type_urls); ++ } ++ ++ auto provider = std::make_unique>( ++ subscription, require_type_urls, factory_context, std::move(default_config), ++ last_filter_in_filter_chain, filter_chain_type, stat_prefix); + +- FilterConfigProviderPtr +- createStaticFilterConfigProvider(const Envoy::Http::FilterFactoryCb& config, ++ // Ensure the subscription starts if it has not already. ++ if (config_source.apply_default_config_without_warming()) { ++ factory_context.initManager().add(provider->initTarget()); ++ } ++ applyLastOrDefaultConfig(subscription, *provider, filter_config_name); ++ return provider; ++ } ++ ++ FilterConfigProviderPtr ++ createStaticFilterConfigProvider(const FactoryCb& config, + const std::string& filter_config_name) override { +- return std::make_unique(config, filter_config_name); ++ return std::make_unique>(config, filter_config_name); + } + + protected: +- virtual Http::FilterFactoryCb ++ virtual ProtobufTypes::MessagePtr + getDefaultConfig(const ProtobufWkt::Any& proto_config, const std::string& filter_config_name, + Server::Configuration::FactoryContext& factory_context, +- const std::string& stat_prefix, bool last_filter_in_filter_chain, +- const std::string& filter_chain_type, +- const absl::flat_hash_set require_type_urls) const PURE; ++ bool last_filter_in_filter_chain, const std::string& filter_chain_type, ++ const absl::flat_hash_set& require_type_urls) const PURE; + }; + +-class HttpFilterConfigProviderManagerImpl : public FilterConfigProviderManagerImpl { ++class HttpFilterConfigProviderManagerImpl ++ : public FilterConfigProviderManagerImpl { ++public: ++ std::tuple ++ getMessage(const envoy::config::core::v3::TypedExtensionConfig& filter_config, ++ Server::Configuration::ServerFactoryContext& factory_context) const override; ++ + protected: +- Http::FilterFactoryCb ++ ProtobufTypes::MessagePtr + getDefaultConfig(const ProtobufWkt::Any& proto_config, const std::string& filter_config_name, + Server::Configuration::FactoryContext& factory_context, +- const std::string& stat_prefix, bool last_filter_in_filter_chain, +- const std::string& filter_chain_type, +- const absl::flat_hash_set require_type_urls) const override; ++ bool last_filter_in_filter_chain, const std::string& filter_chain_type, ++ const absl::flat_hash_set& require_type_urls) const override; + }; + + } // namespace Filter +diff --git a/source/common/formatter/BUILD b/source/common/formatter/BUILD +index 202ad9d030..ade7608fa2 100644 +--- a/source/common/formatter/BUILD ++++ b/source/common/formatter/BUILD +@@ -12,6 +12,9 @@ envoy_cc_library( + name = "substitution_formatter_lib", + srcs = ["substitution_formatter.cc"], + hdrs = ["substitution_formatter.h"], ++ alimesh_deps = [ ++ "//contrib/common/localtime_formatter/source:substitution_formatter_lib", ++ ], + external_deps = ["abseil_str_format"], + deps = [ + "//envoy/api:api_interface", +diff --git a/source/common/formatter/substitution_formatter.cc b/source/common/formatter/substitution_formatter.cc +index cc11f6cf0d..47457caa6a 100644 +--- a/source/common/formatter/substitution_formatter.cc ++++ b/source/common/formatter/substitution_formatter.cc +@@ -27,6 +27,10 @@ + #include "absl/strings/str_split.h" + #include "fmt/format.h" + ++#if defined(ALIMESH) ++#include "contrib/common/localtime_formatter/source/substitution_formatter.h" ++#endif ++ + using Envoy::Config::Metadata; + + namespace Envoy { +@@ -441,6 +445,11 @@ FormatterProviderPtr SubstitutionFormatParser::parseBuiltinCommand(const std::st + return std::make_unique( + HeadersByteSizeFormatter::HeaderType::ResponseTrailers); + } ++#if defined(ALIMESH) ++ else if (absl::StartsWith(token, "LOCAL_START_TIME")) { ++ return std::make_unique(token); ++ } ++#endif + + return nullptr; + } +@@ -685,6 +694,7 @@ private: + }; + + StreamInfoFormatter::StreamInfoFormatter(const std::string& field_name) { ++ // TODO: Change this huge if-else ladder to use a switch case instead. + if (field_name == "REQUEST_DURATION") { + field_extractor_ = std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { +@@ -912,6 +922,11 @@ StreamInfoFormatter::StreamInfoFormatter(const std::string& field_name) { + } + return absl::nullopt; + }); ++ } else if (field_name == "VIRTUAL_CLUSTER_NAME") { ++ field_extractor_ = std::make_unique( ++ [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { ++ return stream_info.virtualClusterName(); ++ }); + } else { + throw EnvoyException(fmt::format("Not supported field in StreamInfo: {}", field_name)); + } +diff --git a/source/common/formatter/substitution_formatter.h b/source/common/formatter/substitution_formatter.h +index 239700da17..509f382634 100644 +--- a/source/common/formatter/substitution_formatter.h ++++ b/source/common/formatter/substitution_formatter.h +@@ -113,6 +113,11 @@ private: + static const size_t ReqParamStart{sizeof("REQ(") - 1}; + static const size_t RespParamStart{sizeof("RESP(") - 1}; + static const size_t TrailParamStart{sizeof("TRAILER(") - 1}; ++ static const size_t StartTimeParamStart{sizeof("START_TIME(") - 1}; ++ ++#if defined(ALIMESH) ++ static const size_t LocalStartTimeParamStart{sizeof("LOCAL_START_TIME(") - 1}; ++#endif + }; + + /** +diff --git a/source/common/grpc/async_client_impl.cc b/source/common/grpc/async_client_impl.cc +index dd63a6bac8..c58fbd7539 100644 +--- a/source/common/grpc/async_client_impl.cc ++++ b/source/common/grpc/async_client_impl.cc +@@ -54,7 +54,7 @@ RawAsyncStream* AsyncClientImpl::startRaw(absl::string_view service_full_name, + auto grpc_stream = + std::make_unique(*this, service_full_name, method_name, callbacks, options); + +- grpc_stream->initialize(false); ++ grpc_stream->initialize(options.buffer_body_for_retry); + if (grpc_stream->hasResetStream()) { + return nullptr; + } +diff --git a/source/common/http/async_client_impl.cc b/source/common/http/async_client_impl.cc +index 2c1da999f2..d0e225d66f 100644 +--- a/source/common/http/async_client_impl.cc ++++ b/source/common/http/async_client_impl.cc +@@ -31,6 +31,11 @@ const absl::optional AsyncStreamImpl::NullConfig::internal_only_headers_; + ++#if defined(ALIMESH) ++const Router::InternalActiveRedirectPoliciesImpl ++ AsyncStreamImpl::RouteEntryImpl::internal_active_redirect_policy_; ++#endif ++ + AsyncClientImpl::AsyncClientImpl(Upstream::ClusterInfoConstSharedPtr cluster, + Stats::Store& stats_store, Event::Dispatcher& dispatcher, + const LocalInfo::LocalInfo& local_info, +diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h +index 608813cc01..a7c5255f12 100644 +--- a/source/common/http/async_client_impl.h ++++ b/source/common/http/async_client_impl.h +@@ -191,6 +191,9 @@ private: + + // Router::RouteEntry + const std::string& clusterName() const override { return cluster_name_; } ++ const Router::RouteStatsContextOptRef routeStatsContext() const override { ++ return Router::RouteStatsContextOptRef(); ++ } + Http::Code clusterNotFoundResponseCode() const override { + return Http::Code::InternalServerError; + } +@@ -259,6 +262,7 @@ private: + } + const Router::VirtualHost& virtualHost() const override { return virtual_host_; } + bool autoHostRewrite() const override { return false; } ++ bool appendXfh() const override { return false; } + bool includeVirtualHostRateLimits() const override { return true; } + const Router::PathMatchCriterion& pathMatchCriterion() const override { + return path_match_criterion_; +@@ -268,6 +272,12 @@ private: + return connect_config_nullopt_; + } + ++#if defined(ALIMESH) ++ const Router::InternalActiveRedirectPolicy& internalActiveRedirectPolicy() const override { ++ return internal_active_redirect_policy_; ++ } ++#endif ++ + bool includeAttemptCountInRequest() const override { return false; } + bool includeAttemptCountInResponse() const override { return false; } + const Router::RouteEntry::UpgradeMap& upgradeMap() const override { return upgrade_map_; } +@@ -283,6 +293,10 @@ private: + static const std::multimap opaque_config_; + static const NullPathMatchCriterion path_match_criterion_; + ++#if defined(ALIMESH) ++ static const Router::InternalActiveRedirectPoliciesImpl internal_active_redirect_policy_; ++#endif ++ + Router::RouteEntry::UpgradeMap upgrade_map_; + const std::string& cluster_name_; + absl::optional timeout_; +diff --git a/source/common/http/codes.cc b/source/common/http/codes.cc +index 0f6b81f64f..48601c53ee 100644 +--- a/source/common/http/codes.cc ++++ b/source/common/http/codes.cc +@@ -32,7 +32,7 @@ CodeStatsImpl::CodeStatsImpl(Stats::SymbolTable& symbol_table) + upstream_rq_completed_(stat_name_pool_.add("upstream_rq_completed")), + upstream_rq_time_(stat_name_pool_.add("upstream_rq_time")), + vcluster_(stat_name_pool_.add("vcluster")), vhost_(stat_name_pool_.add("vhost")), +- zone_(stat_name_pool_.add("zone")) { ++ route_(stat_name_pool_.add("route")), zone_(stat_name_pool_.add("zone")) { + + // Pre-allocate response codes 200, 404, and 503, as those seem quite likely. + // We don't pre-allocate all the HTTP codes because the first 127 allocations +@@ -108,6 +108,16 @@ void CodeStatsImpl::chargeResponseStat(const ResponseStatInfo& info, + {vhost_, info.request_vhost_name_, vcluster_, info.request_vcluster_name_, rq_code}); + } + ++ // Handle route level stats. ++ if (!info.request_route_name_.empty()) { ++ incCounter(info.global_scope_, {vhost_, info.request_vhost_name_, route_, ++ info.request_route_name_, upstream_rq_completed_}); ++ incCounter(info.global_scope_, ++ {vhost_, info.request_vhost_name_, route_, info.request_route_name_, rq_group}); ++ incCounter(info.global_scope_, ++ {vhost_, info.request_vhost_name_, route_, info.request_route_name_, rq_code}); ++ } ++ + // Handle per zone stats. + if (!info.from_zone_.empty() && !info.to_zone_.empty()) { + incCounter(info.cluster_scope_, +@@ -151,6 +161,13 @@ void CodeStatsImpl::chargeResponseTiming(const ResponseTimingInfo& info) const { + Stats::Histogram::Unit::Milliseconds, count); + } + ++ if (!info.request_route_name_.empty()) { ++ recordHistogram( ++ info.global_scope_, ++ {vhost_, info.request_vhost_name_, route_, info.request_route_name_, upstream_rq_time_}, ++ Stats::Histogram::Unit::Milliseconds, count); ++ } ++ + // Handle per zone stats. + if (!info.from_zone_.empty() && !info.to_zone_.empty()) { + recordHistogram(info.cluster_scope_, +diff --git a/source/common/http/codes.h b/source/common/http/codes.h +index d3f78ee16c..bb731aa702 100644 +--- a/source/common/http/codes.h ++++ b/source/common/http/codes.h +@@ -22,6 +22,7 @@ struct CodeStats::ResponseStatInfo { + bool internal_request_; + Stats::StatName request_vhost_name_; + Stats::StatName request_vcluster_name_; ++ Stats::StatName request_route_name_; + Stats::StatName from_zone_; + Stats::StatName to_zone_; + bool upstream_canary_; +@@ -36,6 +37,7 @@ struct CodeStats::ResponseTimingInfo { + bool internal_request_; + Stats::StatName request_vhost_name_; + Stats::StatName request_vcluster_name_; ++ Stats::StatName request_route_name_; + Stats::StatName from_zone_; + Stats::StatName to_zone_; + }; +@@ -82,6 +84,7 @@ private: + const Stats::StatName upstream_rq_time_; + const Stats::StatName vcluster_; + const Stats::StatName vhost_; ++ const Stats::StatName route_; + const Stats::StatName zone_; + + // Use an array of atomic pointers to hold StatNameStorage objects for +diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc +index 90f6be301b..4715a90908 100644 +--- a/source/common/http/conn_manager_impl.cc ++++ b/source/common/http/conn_manager_impl.cc +@@ -178,9 +178,14 @@ ConnectionManagerImpl::~ConnectionManagerImpl() { + user_agent_.completeConnectionLength(*conn_length_); + } + +-void ConnectionManagerImpl::checkForDeferredClose() { ++void ConnectionManagerImpl::checkForDeferredClose(bool skip_delay_close) { ++ Network::ConnectionCloseType close = Network::ConnectionCloseType::FlushWriteAndDelay; ++ if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.skip_delay_close") && ++ skip_delay_close) { ++ close = Network::ConnectionCloseType::FlushWrite; ++ } + if (drain_state_ == DrainState::Closing && streams_.empty() && !codec_->wantsToWrite()) { +- doConnectionClose(Network::ConnectionCloseType::FlushWriteAndDelay, absl::nullopt, ++ doConnectionClose(close, absl::nullopt, + StreamInfo::ResponseCodeDetails::get().DownstreamLocalDisconnect); + } + } +@@ -197,8 +202,8 @@ void ConnectionManagerImpl::doEndStream(ActiveStream& stream) { + // here is when Envoy "ends" the stream by calling recreateStream at which point recreateStream + // explicitly nulls out response_encoder to avoid the downstream being notified of the + // Envoy-internal stream instance being ended. +- if (stream.response_encoder_ != nullptr && +- (!stream.filter_manager_.remoteComplete() || !stream.state_.codec_saw_local_complete_)) { ++ if (stream.response_encoder_ != nullptr && (!stream.filter_manager_.remoteDecodeComplete() || ++ !stream.state_.codec_saw_local_complete_)) { + // Indicate local is complete at this point so that if we reset during a continuation, we don't + // raise further data or trailers. + ENVOY_STREAM_LOG(debug, "doEndStream() resetting stream", stream); +@@ -234,7 +239,16 @@ void ConnectionManagerImpl::doEndStream(ActiveStream& stream) { + drain_state_ = DrainState::Closing; + } + +- checkForDeferredClose(); ++ // If HTTP/1.0 has no content length, it is framed by close and won't consider ++ // the request complete until the FIN is read. Don't delay close in this case. ++ bool http_10_sans_cl = (codec_->protocol() == Protocol::Http10) && ++ (!stream.response_headers_ || !stream.response_headers_->ContentLength()); ++ // We also don't delay-close in the case of HTTP/1.1 where the request is ++ // fully read, as there's no race condition to avoid. ++ bool connection_close = stream.state_.saw_connection_close_; ++ bool request_complete = stream.filter_manager_.remoteDecodeComplete(); ++ ++ checkForDeferredClose(connection_close && (request_complete || http_10_sans_cl)); + } + + void ConnectionManagerImpl::doDeferredStreamDestroy(ActiveStream& stream) { +@@ -364,7 +378,7 @@ Network::FilterStatus ConnectionManagerImpl::onData(Buffer::Instance& data, bool + ASSERT(status.ok()); + + // Processing incoming data may release outbound data so check for closure here as well. +- checkForDeferredClose(); ++ checkForDeferredClose(false); + + // The HTTP/1 codec will pause dispatch after a single message is complete. We want to + // either redispatch if there are no streams and we have more data. If we have a single +@@ -530,7 +544,7 @@ void ConnectionManagerImpl::onDrainTimeout() { + ASSERT(drain_state_ != DrainState::NotDraining); + codec_->goAway(); + drain_state_ = DrainState::Closing; +- checkForDeferredClose(); ++ checkForDeferredClose(false); + } + + void ConnectionManagerImpl::chargeTracingStats(const Tracing::Reason& tracing_reason, +@@ -778,6 +792,16 @@ void ConnectionManagerImpl::ActiveStream::onStreamMaxDurationReached() { + + void ConnectionManagerImpl::ActiveStream::chargeStats(const ResponseHeaderMap& headers) { + uint64_t response_code = Utility::getResponseStatus(headers); ++ ++#if defined(ALIMESH) ++ if (Grpc::Common::hasGrpcContentType(headers)) { ++ absl::optional grpc_status = Grpc::Common::getGrpcStatus(headers); ++ if (grpc_status.has_value()) { ++ response_code = Grpc::Utility::grpcToHttpStatus(grpc_status.value()); ++ } ++ } ++#endif ++ + filter_manager_.streamInfo().response_code_ = response_code; + + if (filter_manager_.streamInfo().health_check_request_) { +@@ -1416,7 +1440,7 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ResponseHeaderMap& heade + // If we are destroying a stream before remote is complete and the connection does not support + // multiplexing, we should disconnect since we don't want to wait around for the request to + // finish. +- if (!filter_manager_.remoteComplete()) { ++ if (!filter_manager_.remoteDecodeComplete()) { + if (connection_manager_.codec_->protocol() < Protocol::Http2) { + connection_manager_.drain_state_ = DrainState::Closing; + } +diff --git a/source/common/http/conn_manager_impl.h b/source/common/http/conn_manager_impl.h +index b83e0aa264..b336352fff 100644 +--- a/source/common/http/conn_manager_impl.h ++++ b/source/common/http/conn_manager_impl.h +@@ -398,7 +398,7 @@ private: + * Check to see if the connection can be closed after gracefully waiting to send pending codec + * data. + */ +- void checkForDeferredClose(); ++ void checkForDeferredClose(bool skip_deferred_close); + + /** + * Do a delayed destruction of a stream to allow for stack unwind. Also calls onDestroy() for +diff --git a/source/common/http/filter_manager.cc b/source/common/http/filter_manager.cc +index fc15f8041f..46e9fda6f6 100644 +--- a/source/common/http/filter_manager.cc ++++ b/source/common/http/filter_manager.cc +@@ -303,6 +303,12 @@ bool ActiveStreamDecoderFilter::canContinue() { + return !parent_.state_.local_complete_; + } + ++bool ActiveStreamEncoderFilter::canContinue() { ++ // As with ActiveStreamDecoderFilter::canContinue() make sure we do not ++ // continue if a local reply has been sent. ++ return !parent_.state_.remote_encode_complete_; ++} ++ + Buffer::InstancePtr ActiveStreamDecoderFilter::createBuffer() { + auto buffer = dispatcher().getWatermarkFactory().createBuffer( + [this]() -> void { this->requestDataDrained(); }, +@@ -316,7 +322,7 @@ Buffer::InstancePtr& ActiveStreamDecoderFilter::bufferedData() { + return parent_.buffered_request_data_; + } + +-bool ActiveStreamDecoderFilter::complete() { return parent_.state_.remote_complete_; } ++bool ActiveStreamDecoderFilter::complete() { return parent_.state_.remote_decode_complete_; } + + void ActiveStreamDecoderFilter::doHeaders(bool end_stream) { + parent_.decodeHeaders(this, *parent_.filter_manager_callbacks_.requestHeaders(), end_stream); +@@ -828,8 +834,8 @@ void FilterManager::decodeMetadata(ActiveStreamDecoderFilter* filter, MetadataMa + } + + void FilterManager::maybeEndDecode(bool end_stream) { +- ASSERT(!state_.remote_complete_); +- state_.remote_complete_ = end_stream; ++ ASSERT(!state_.remote_decode_complete_); ++ state_.remote_decode_complete_ = end_stream; + if (end_stream) { + stream_info_.onLastDownstreamRxByteReceived(); + ENVOY_STREAM_LOG(debug, "request end stream", *this); +@@ -1338,6 +1344,8 @@ void FilterManager::encodeTrailers(ActiveStreamEncoderFilter* filter, + + void FilterManager::maybeEndEncode(bool end_stream) { + if (end_stream) { ++ ASSERT(!state_.remote_encode_complete_); ++ state_.remote_encode_complete_ = true; + filter_manager_callbacks_.endStream(); + } + } +@@ -1627,6 +1635,7 @@ Http1StreamEncoderOptionsOptRef ActiveStreamEncoderFilter::http1StreamEncoderOpt + } + + void ActiveStreamEncoderFilter::responseDataTooLarge() { ++ ENVOY_STREAM_LOG(debug, "response data too large watermark exceeded", parent_); + if (parent_.state_.encoder_filters_streaming_) { + onEncoderFilterAboveWriteBufferHighWatermark(); + } else { +diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h +index 633fa6862d..9d8718a48c 100644 +--- a/source/common/http/filter_manager.h ++++ b/source/common/http/filter_manager.h +@@ -315,7 +315,7 @@ struct ActiveStreamEncoderFilter : public ActiveStreamFilterBase, + : ActiveStreamFilterBase(parent, dual_filter, std::move(match_state)), handle_(filter) {} + + // ActiveStreamFilterBase +- bool canContinue() override { return true; } ++ bool canContinue() override; + Buffer::InstancePtr createBuffer() override; + Buffer::InstancePtr& bufferedData() override; + bool complete() override; +@@ -907,7 +907,7 @@ public: + /** + * Whether remote processing has been marked as complete. + */ +- bool remoteComplete() const { return state_.remote_complete_; } ++ bool remoteDecodeComplete() const { return state_.remote_decode_complete_; } + + /** + * Instructs the FilterManager to not create a filter chain. This makes it possible to issue +@@ -1059,14 +1059,16 @@ private: + + struct State { + State() +- : remote_complete_(false), local_complete_(false), has_continue_headers_(false), +- created_filter_chain_(false), is_head_request_(false), is_grpc_request_(false), +- non_100_response_headers_encoded_(false), under_on_local_reply_(false), +- decoder_filter_chain_aborted_(false), encoder_filter_chain_aborted_(false) {} ++ : remote_encode_complete_(false), remote_decode_complete_(false), local_complete_(false), ++ has_continue_headers_(false), created_filter_chain_(false), is_head_request_(false), ++ is_grpc_request_(false), non_100_response_headers_encoded_(false), ++ under_on_local_reply_(false), decoder_filter_chain_aborted_(false), ++ encoder_filter_chain_aborted_(false) {} + + uint32_t filter_call_state_{0}; + +- bool remote_complete_ : 1; ++ bool remote_encode_complete_ : 1; ++ bool remote_decode_complete_ : 1; + bool local_complete_ : 1; // This indicates that local is complete prior to filter processing. + // A filter can still stop the stream from being complete as seen + // by the codec. +diff --git a/source/common/http/headers.h b/source/common/http/headers.h +index ccae31bf70..5420eb4475 100644 +--- a/source/common/http/headers.h ++++ b/source/common/http/headers.h +@@ -52,6 +52,7 @@ class CustomHeaderValues { + public: + const LowerCaseString Accept{"accept"}; + const LowerCaseString AcceptEncoding{"accept-encoding"}; ++ const LowerCaseString AccessControlRequestHeaders{"access-control-request-headers"}; + const LowerCaseString AccessControlRequestMethod{"access-control-request-method"}; + const LowerCaseString AccessControlAllowOrigin{"access-control-allow-origin"}; + const LowerCaseString AccessControlAllowHeaders{"access-control-allow-headers"}; +@@ -115,6 +116,16 @@ public: + const std::string AcceptEncoding{"Accept-Encoding"}; + const std::string Wildcard{"*"}; + } VaryValues; ++ ++#if defined(ALIMESH) ++ struct { ++ const LowerCaseString TriArriveTime{"req-arrive-time"}; ++ const LowerCaseString TriCostTime{"req-cost-time"}; ++ const LowerCaseString TriStartTime{"req-start-time"}; ++ const LowerCaseString TriRespStartTime{"resp-start-time"}; ++ const LowerCaseString EnvoyOriginalHost{"original-host"}; ++ } AliExtendedValues; ++#endif + }; + + using CustomHeaders = ConstSingleton; +diff --git a/source/common/http/utility.cc b/source/common/http/utility.cc +index ac822a9515..b60199da72 100644 +--- a/source/common/http/utility.cc ++++ b/source/common/http/utility.cc +@@ -387,6 +387,14 @@ void Utility::appendVia(RequestOrResponseHeaderMap& headers, const std::string& + headers.appendVia(via, ", "); + } + ++void Utility::updateAuthority(RequestHeaderMap& headers, absl::string_view hostname, ++ const bool append_xfh) { ++ if (append_xfh && !headers.getHostValue().empty()) { ++ headers.appendForwardedHost(headers.getHostValue(), ","); ++ } ++ headers.setHost(hostname); ++} ++ + std::string Utility::createSslRedirectPath(const RequestHeaderMap& headers) { + ASSERT(headers.Host()); + ASSERT(headers.Path()); +diff --git a/source/common/http/utility.h b/source/common/http/utility.h +index 5038ebce1e..dff9a474d8 100644 +--- a/source/common/http/utility.h ++++ b/source/common/http/utility.h +@@ -194,6 +194,14 @@ void appendXff(RequestHeaderMap& headers, const Network::Address::Instance& remo + */ + void appendVia(RequestOrResponseHeaderMap& headers, const std::string& via); + ++/** ++ * Update authority with the specified hostname. ++ * @param headers headers where authority should be updated. ++ * @param hostname hostname that authority should be updated with. ++ * @param append_xfh append the original authority to the x-forwarded-host header. ++ */ ++void updateAuthority(RequestHeaderMap& headers, absl::string_view hostname, bool append_xfh); ++ + /** + * Creates an SSL (https) redirect path based on the input host and path headers. + * @param headers supplies the request headers. +diff --git a/source/common/network/socket_impl.cc b/source/common/network/socket_impl.cc +index c19ac2542f..72509632bf 100644 +--- a/source/common/network/socket_impl.cc ++++ b/source/common/network/socket_impl.cc +@@ -71,7 +71,16 @@ Api::SysCallIntResult SocketImpl::bind(Network::Address::InstanceConstSharedPtr + + bind_result = io_handle_->bind(address); + if (bind_result.return_value_ == 0 && address->ip()->port() == 0) { ++#if defined(ALIMESH) ++ try { ++ connection_info_provider_->setLocalAddress(io_handle_->localAddress()); ++ } catch (const EnvoyException& ex) { ++ bind_result.return_value_ = -1; ++ ENVOY_LOG_MISC(critical, "envoy exception raised in SocketImpl::bind(): {}", ex.what()); ++ } ++#else + connection_info_provider_->setLocalAddress(io_handle_->localAddress()); ++#endif + } + return bind_result; + } +diff --git a/source/common/router/BUILD b/source/common/router/BUILD +index 4e0bbe9145..3690d8689a 100644 +--- a/source/common/router/BUILD ++++ b/source/common/router/BUILD +@@ -31,6 +31,9 @@ envoy_cc_library( + name = "config_lib", + srcs = ["config_impl.cc"], + hdrs = ["config_impl.h"], ++ alimesh_deps = [ ++ "//contrib/common/active_redirect/source:active_redirect_policy_lib", ++ ], + external_deps = ["abseil_optional"], + deps = [ + ":config_utility_lib", +@@ -43,6 +46,7 @@ envoy_cc_library( + ":tls_context_match_criteria_lib", + "//envoy/config:typed_metadata_interface", + "//envoy/http:header_map_interface", ++ "//envoy/router:cluster_specifier_plugin_interface", + "//envoy/router:router_interface", + "//envoy/runtime:runtime_interface", + "//envoy/server:filter_config_interface", # TODO(rodaine): break dependency on server +@@ -99,6 +103,7 @@ envoy_cc_library( + "//envoy/router:context_interface", + "//envoy/router:router_interface", + "//envoy/stats:stats_macros", ++ "//source/common/config:utility_lib", + ], + ) + +@@ -275,6 +280,9 @@ envoy_cc_library( + "router.h", + "upstream_request.h", + ], ++ alimesh_deps = [ ++ "//envoy/stats:timespan_interface", ++ ], + deps = [ + ":config_lib", + ":context_lib", +diff --git a/source/common/router/config_impl.cc b/source/common/router/config_impl.cc +index d756c60796..5bdc137011 100644 +--- a/source/common/router/config_impl.cc ++++ b/source/common/router/config_impl.cc +@@ -70,6 +70,36 @@ const envoy::config::route::v3::WeightedCluster::ClusterWeight& validateWeighted + return cluster; + } + ++// If the implementation of a cluster specifier plugin is not provided in current Envoy and the ++// plugin is set to optional, then this null plugin will be used as a placeholder. ++class NullClusterSpecifierPlugin : public ClusterSpecifierPlugin { ++public: ++ RouteConstSharedPtr route(const RouteEntry&, const Http::RequestHeaderMap&) const override { ++ return nullptr; ++ } ++}; ++ ++ClusterSpecifierPluginSharedPtr ++getClusterSpecifierPluginByTheProto(const envoy::config::route::v3::ClusterSpecifierPlugin& plugin, ++ ProtobufMessage::ValidationVisitor& validator, ++ Server::Configuration::ServerFactoryContext& factory_context) { ++ auto* factory = ++ Envoy::Config::Utility::getFactory(plugin.extension()); ++ if (factory == nullptr) { ++ if (plugin.is_optional()) { ++ return std::make_shared(); ++ } ++ throw EnvoyException( ++ fmt::format("Didn't find a registered implementation for '{}' with type URL: '{}'", ++ plugin.extension().name(), ++ Envoy::Config::Utility::getFactoryType(plugin.extension().typed_config()))); ++ } ++ ASSERT(factory != nullptr); ++ auto config = ++ Envoy::Config::Utility::translateToFactoryConfig(plugin.extension(), validator, *factory); ++ return factory->createClusterSpecifierPlugin(*config, factory_context); ++} ++ + } // namespace + + const std::string& OriginalConnectPort::key() { +@@ -336,7 +366,8 @@ RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, + route.route().has_host_rewrite_path_regex() + ? route.route().host_rewrite_path_regex().substitution() + : ""), +- cluster_name_(route.route().cluster()), cluster_header_name_(route.route().cluster_header()), ++ append_xfh_(route.route().append_x_forwarded_host()), cluster_name_(route.route().cluster()), ++ cluster_header_name_(route.route().cluster_header()), + cluster_not_found_response_code_(ConfigUtility::parseClusterNotFoundResponseCode( + route.route().cluster_not_found_response_code())), + timeout_(PROTOBUF_GET_MS_OR_DEFAULT(route.route(), timeout, DEFAULT_ROUTE_TIMEOUT_MS)), +@@ -389,7 +420,13 @@ RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, + vhost_.globalRouteConfig().maxDirectResponseBodySizeBytes())), + per_filter_configs_(route.typed_per_filter_config(), optional_http_filters, factory_context, + validator), ++#if !defined(ALIMESH) + route_name_(route.name()), time_source_(factory_context.mainThreadDispatcher().timeSource()) { ++#else ++ route_name_(route.name()), time_source_(factory_context.mainThreadDispatcher().timeSource()), ++ internal_active_redirect_policy_( ++ buildActiveInternalRedirectPolicy(route.route(), validator, route.name())) { ++#endif + if (route.route().has_metadata_match()) { + const auto filter_it = route.route().metadata_match().filter_metadata().find( + Envoy::Config::MetadataFilters::get().ENVOY_LB); +@@ -427,6 +464,26 @@ RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, + throw EnvoyException(fmt::format("Sum of weights in the weighted_cluster should add up to {}", + total_cluster_weight_)); + } ++ ++#if defined(ALIMESH) ++ if (route.route().weighted_clusters().has_inline_cluster_specifier_plugin()) { ++ cluster_specifier_plugin_ = getClusterSpecifierPluginByTheProto( ++ route.route().weighted_clusters().inline_cluster_specifier_plugin(), validator, ++ factory_context); ++ } else if (!route.route().weighted_clusters().cluster_specifier_plugin().empty()) { ++ cluster_specifier_plugin_ = vhost_.globalRouteConfig().clusterSpecifierPlugin( ++ route.route().weighted_clusters().cluster_specifier_plugin()); ++ } ++#endif ++ ++ } else if (route.route().cluster_specifier_case() == ++ envoy::config::route::v3::RouteAction::ClusterSpecifierCase:: ++ kInlineClusterSpecifierPlugin) { ++ cluster_specifier_plugin_ = getClusterSpecifierPluginByTheProto( ++ route.route().inline_cluster_specifier_plugin(), validator, factory_context); ++ } else if (route.route().has_cluster_specifier_plugin()) { ++ cluster_specifier_plugin_ = ++ vhost_.globalRouteConfig().clusterSpecifierPlugin(route.route().cluster_specifier_plugin()); + } + + for (const auto& query_parameter : route.match().query_parameters()) { +@@ -493,6 +550,20 @@ RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, + "not be stripped: {}", + path_redirect_); + } ++ ENVOY_LOG(info, "route stats is {}, name is {}", route.stat_prefix(), route.name()); ++ if (!route.stat_prefix().empty()) { ++ route_stats_context_ = std::make_unique( ++ factory_context.scope(), factory_context.routerContext().routeStatNames(), vhost.statName(), ++ route.stat_prefix()); ++ } else if (!route.name().empty()) { ++ // Added by Ingress ++ // use route_name as default stat_prefix ++ route_stats_context_ = std::make_unique( ++ factory_context.scope(), factory_context.routerContext().routeStatNames(), vhost.statName(), ++ route.name()); ++ } ++ // End Added ++ + } + + bool RouteEntryImplBase::evaluateRuntimeMatch(const uint64_t random_value) const { +@@ -590,6 +661,11 @@ void RouteEntryImplBase::finalizeRequestHeaders(Http::RequestHeaderMap& headers, + request_headers_parser_->evaluateHeaders(headers, stream_info); + } + ++#if defined(ALIMESH) ++ headers.setReferenceKey(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost, ++ headers.getHostValue()); ++#endif ++ + // Restore the port if this was a CONNECT request. + // Note this will restore the port for HTTP/2 CONNECT-upgrades as well as as HTTP/1.1 style + // CONNECT requests. +@@ -601,7 +677,7 @@ void RouteEntryImplBase::finalizeRequestHeaders(Http::RequestHeaderMap& headers, + } + + if (!host_rewrite_.empty()) { +- headers.setHost(host_rewrite_); ++ Http::Utility::updateAuthority(headers, host_rewrite_, append_xfh_); + } else if (auto_host_rewrite_header_) { + const auto header = headers.get(*auto_host_rewrite_header_); + if (!header.empty()) { +@@ -609,14 +685,16 @@ void RouteEntryImplBase::finalizeRequestHeaders(Http::RequestHeaderMap& headers, + // value is used. + const absl::string_view header_value = header[0]->value().getStringView(); + if (!header_value.empty()) { +- headers.setHost(header_value); ++ Http::Utility::updateAuthority(headers, header_value, append_xfh_); + } + } + } else if (host_rewrite_path_regex_ != nullptr) { + const std::string path(headers.getPathValue()); + absl::string_view just_path(Http::PathUtil::removeQueryAndFragment(path)); +- headers.setHost( +- host_rewrite_path_regex_->replaceAll(just_path, host_rewrite_path_regex_substitution_)); ++ Http::Utility::updateAuthority( ++ headers, ++ host_rewrite_path_regex_->replaceAll(just_path, host_rewrite_path_regex_substitution_), ++ append_xfh_); + } + + // Handle path rewrite +@@ -946,6 +1024,30 @@ InternalRedirectPolicyImpl RouteEntryImplBase::buildInternalRedirectPolicy( + return InternalRedirectPolicyImpl(policy_config, validator, current_route_name); + } + ++#if defined(ALIMESH) ++InternalActiveRedirectPoliciesImpl RouteEntryImplBase::buildActiveInternalRedirectPolicy( ++ const envoy::config::route::v3::RouteAction& route_config, ++ ProtobufMessage::ValidationVisitor& validator, absl::string_view current_route_name) const { ++ if (route_config.has_internal_active_redirect_policy()) { ++ return InternalActiveRedirectPoliciesImpl(route_config.internal_active_redirect_policy(), ++ validator, current_route_name); ++ } ++ envoy::config::route::v3::InternalActiveRedirectPolicy policy_config; ++ switch (route_config.internal_redirect_action()) { ++ case envoy::config::route::v3::RouteAction::HANDLE_INTERNAL_REDIRECT: ++ break; ++ case envoy::config::route::v3::RouteAction::PASS_THROUGH_INTERNAL_REDIRECT: ++ FALLTHRU; ++ default: ++ return InternalActiveRedirectPoliciesImpl(); ++ } ++ if (route_config.has_max_internal_redirects()) { ++ *policy_config.mutable_max_internal_redirects() = route_config.max_internal_redirects(); ++ } ++ return InternalActiveRedirectPoliciesImpl(policy_config, validator, current_route_name); ++} ++#endif ++ + DecoratorConstPtr RouteEntryImplBase::parseDecorator(const envoy::config::route::v3::Route& route) { + DecoratorConstPtr ret; + if (route.has_decorator()) { +@@ -1000,16 +1102,20 @@ RouteEntryImplBase::pickClusterViaClusterHeader(const Http::LowerCaseString& clu + return std::make_shared(this, final_cluster_name); + } + +-RouteConstSharedPtr RouteEntryImplBase::clusterEntry(const Http::HeaderMap& headers, ++RouteConstSharedPtr RouteEntryImplBase::clusterEntry(const Http::RequestHeaderMap& headers, + uint64_t random_value) const { + // Gets the route object chosen from the list of weighted clusters + // (if there is one) or returns self. + if (weighted_clusters_.empty()) { + if (!cluster_name_.empty() || isDirectResponse()) { + return shared_from_this(); +- } else { +- ASSERT(!cluster_header_name_.get().empty()); ++ } else if (!cluster_header_name_.get().empty()) { + return pickClusterViaClusterHeader(cluster_header_name_, headers); ++ } else { ++ // TODO(wbpcode): make the cluster header or weighted clusters an implementation of the ++ // cluster specifier plugin. ++ ASSERT(cluster_specifier_plugin_ != nullptr); ++ return cluster_specifier_plugin_->route(*this, headers); + } + } + return pickWeightedCluster(headers, random_value, true); +@@ -1035,6 +1141,18 @@ RouteConstSharedPtr RouteEntryImplBase::pickWeightedCluster(const Http::HeaderMa + } + + if (selected_value >= begin && selected_value < end) { ++#if defined(ALIMESH) ++ if (cluster_specifier_plugin_ != nullptr) { ++ auto request_header = dynamic_cast(&headers); ++ if (!cluster->clusterHeaderName().get().empty() && ++ !headers.get(cluster->clusterHeaderName()).empty()) { ++ auto route = pickClusterViaClusterHeader(cluster->clusterHeaderName(), headers); ++ auto route_entry = dynamic_cast(route.get()); ++ return cluster_specifier_plugin_->route(*route_entry, *request_header); ++ } ++ return cluster_specifier_plugin_->route(*cluster, *request_header); ++ } ++#endif + if (!cluster->clusterHeaderName().get().empty() && + !headers.get(cluster->clusterHeaderName()).empty()) { + return pickClusterViaClusterHeader(cluster->clusterHeaderName(), headers); +@@ -1372,7 +1490,7 @@ VirtualHostImpl::VirtualClusterEntry::VirtualClusterEntry( + const envoy::config::route::v3::VirtualCluster& virtual_cluster, Stats::Scope& scope, + const VirtualClusterStatNames& stat_names) + : StatNameProvider(virtual_cluster.name(), scope.symbolTable()), +- VirtualClusterBase(stat_name_storage_.statName(), ++ VirtualClusterBase(virtual_cluster.name(), stat_name_storage_.statName(), + scope.scopeFromStatName(stat_name_storage_.statName()), stat_names) { + if (virtual_cluster.headers().empty()) { + throw EnvoyException("virtual clusters must define 'headers'"); +@@ -1469,6 +1587,21 @@ RouteConstSharedPtr VirtualHostImpl::getRouteFromEntries(const RouteCallback& cb + return nullptr; + } + ++#if defined(ALIMESH) ++ RouteConstSharedPtr redirect_route = SSL_PERMANENT_REDIRECT_ROUTE; ++ // only return 301 when http method is GET or HEAD ++ if (headers.Method() && (headers.Method()->value() == Http::Headers::get().MethodValues.Get || ++ headers.Method()->value() == Http::Headers::get().MethodValues.Head)) { ++ redirect_route = SSL_REDIRECT_ROUTE; ++ } ++ // First check for ssl redirect. ++ if (ssl_requirements_ == SslRequirements::All && scheme != "https") { ++ return redirect_route; ++ } else if (ssl_requirements_ == SslRequirements::ExternalOnly && scheme != "https" && ++ !Http::HeaderUtility::isEnvoyInternalRequest(headers)) { ++ return redirect_route; ++ } ++#else + // First check for ssl redirect. + if (ssl_requirements_ == SslRequirements::All && scheme != "https") { + return SSL_REDIRECT_ROUTE; +@@ -1476,6 +1609,7 @@ RouteConstSharedPtr VirtualHostImpl::getRouteFromEntries(const RouteCallback& cb + !Http::HeaderUtility::isEnvoyInternalRequest(headers)) { + return SSL_REDIRECT_ROUTE; + } ++#endif + + // Check for a route that matches the request. + for (auto route = routes_.begin(); route != routes_.end(); ++route) { +@@ -1568,6 +1702,12 @@ const Envoy::Config::TypedMetadataImpl + const std::shared_ptr VirtualHostImpl::SSL_REDIRECT_ROUTE{ + new SslRedirectRoute()}; + ++#if defined(ALIMESH) ++const SslPermanentRedirector SslPermanentRedirectRoute::SSL_PERMANENT_REDIRECTOR; ++const std::shared_ptr ++ VirtualHostImpl::SSL_PERMANENT_REDIRECT_ROUTE{new SslPermanentRedirectRoute}; ++#endif ++ + const VirtualCluster* + VirtualHostImpl::virtualClusterFromEntries(const Http::HeaderMap& headers) const { + for (const VirtualClusterEntry& entry : virtual_clusters_) { +@@ -1594,6 +1734,13 @@ ConfigImpl::ConfigImpl(const envoy::config::route::v3::RouteConfiguration& confi + max_direct_response_body_size_bytes_( + PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, max_direct_response_body_size_bytes, + DEFAULT_MAX_DIRECT_RESPONSE_BODY_SIZE_BYTES)) { ++ // Initialize all cluster specifier plugins before creating route matcher. Because the route may ++ // reference it by name. ++ for (const auto& plugin_proto : config.cluster_specifier_plugins()) { ++ auto plugin = getClusterSpecifierPluginByTheProto(plugin_proto, validator, factory_context); ++ cluster_specifier_plugins_.emplace(plugin_proto.extension().name(), std::move(plugin)); ++ } ++ + route_matcher_ = std::make_unique( + config, optional_http_filters, *this, factory_context, validator, + PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, validate_clusters, validate_clusters_default)); +@@ -1608,6 +1755,16 @@ ConfigImpl::ConfigImpl(const envoy::config::route::v3::RouteConfiguration& confi + config.response_headers_to_remove()); + } + ++ClusterSpecifierPluginSharedPtr ++ConfigImpl::clusterSpecifierPlugin(absl::string_view provider) const { ++ auto iter = cluster_specifier_plugins_.find(provider); ++ if (iter == cluster_specifier_plugins_.end() || iter->second == nullptr) { ++ throw EnvoyException( ++ fmt::format("Unknown cluster specifier plugin name: {} is used in the route", provider)); ++ } ++ return iter->second; ++} ++ + RouteConstSharedPtr ConfigImpl::route(const RouteCallback& cb, + const Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& stream_info, +diff --git a/source/common/router/config_impl.h b/source/common/router/config_impl.h +index 659861f3b1..308d0ad83c 100644 +--- a/source/common/router/config_impl.h ++++ b/source/common/router/config_impl.h +@@ -13,6 +13,8 @@ + #include "envoy/config/core/v3/base.pb.h" + #include "envoy/config/route/v3/route.pb.h" + #include "envoy/config/route/v3/route_components.pb.h" ++#include "envoy/config/route/v3/route_components.pb.validate.h" ++#include "envoy/router/cluster_specifier_plugin.h" + #include "envoy/router/router.h" + #include "envoy/runtime/runtime.h" + #include "envoy/server/filter_config.h" +@@ -34,6 +36,10 @@ + #include "absl/container/node_hash_map.h" + #include "absl/types/optional.h" + ++#if defined(ALIMESH) ++#include "contrib/common/active_redirect/source/active_redirect_policy_impl.h" ++#endif ++ + namespace Envoy { + namespace Router { + +@@ -141,6 +147,22 @@ private: + typed_metadata_; + }; + ++#if defined(ALIMESH) ++class SslPermanentRedirector : public SslRedirector { ++public: ++ Http::Code responseCode() const override { return Http::Code::PermanentRedirect; } ++}; ++class SslPermanentRedirectRoute : public SslRedirectRoute { ++public: ++ const DirectResponseEntry* directResponseEntry() const override { ++ return &SSL_PERMANENT_REDIRECTOR; ++ } ++ ++private: ++ static const SslPermanentRedirector SSL_PERMANENT_REDIRECTOR; ++}; ++#endif ++ + /** + * Implementation of CorsPolicy that reads from the proto route and virtual host config. + */ +@@ -234,16 +256,20 @@ private: + + struct VirtualClusterBase : public VirtualCluster { + public: +- VirtualClusterBase(Stats::StatName stat_name, Stats::ScopePtr&& scope, +- const VirtualClusterStatNames& stat_names) +- : stat_name_(stat_name), scope_(std::move(scope)), ++ VirtualClusterBase(const absl::optional& name, Stats::StatName stat_name, ++ Stats::ScopePtr&& scope, const VirtualClusterStatNames& stat_names) ++ : name_(name), stat_name_(stat_name), scope_(std::move(scope)), + stats_(generateStats(*scope_, stat_names)) {} + + // Router::VirtualCluster ++ // name_ and stat_name_ are two different representations for the same string, retained in ++ // memory to avoid symbol-table locks that would be needed when converting on-the-fly. ++ const absl::optional& name() const override { return name_; } + Stats::StatName statName() const override { return stat_name_; } + VirtualClusterStats& stats() const override { return stats_; } + + private: ++ const absl::optional name_; + const Stats::StatName stat_name_; + Stats::ScopePtr scope_; + mutable VirtualClusterStats stats_; +@@ -257,11 +283,14 @@ private: + + struct CatchAllVirtualCluster : public VirtualClusterBase { + CatchAllVirtualCluster(Stats::Scope& scope, const VirtualClusterStatNames& stat_names) +- : VirtualClusterBase(stat_names.other_, scope.scopeFromStatName(stat_names.other_), +- stat_names) {} ++ : VirtualClusterBase(absl::nullopt, stat_names.other_, ++ scope.scopeFromStatName(stat_names.other_), stat_names) {} + }; + + static const std::shared_ptr SSL_REDIRECT_ROUTE; ++#if defined(ALIMESH) ++ static const std::shared_ptr SSL_PERMANENT_REDIRECT_ROUTE; ++#endif + + const Stats::StatNameManagedStorage stat_name_storage_; + Stats::ScopePtr vcluster_scope_; +@@ -516,6 +545,12 @@ public: + + // Router::RouteEntry + const std::string& clusterName() const override; ++ const RouteStatsContextOptRef routeStatsContext() const override { ++ if (route_stats_context_ != nullptr) { ++ return *route_stats_context_; ++ } ++ return RouteStatsContextOptRef(); ++ } + Http::Code clusterNotFoundResponseCode() const override { + return cluster_not_found_response_code_; + } +@@ -544,6 +579,15 @@ public: + const InternalRedirectPolicy& internalRedirectPolicy() const override { + return internal_redirect_policy_; + } ++#if defined(ALIMESH) ++ const InternalActiveRedirectPolicy& internalActiveRedirectPolicy() const override { ++ return internal_active_redirect_policy_; ++ } ++ ++ RouteConstSharedPtr clone(const std::string& name) const { ++ return std::make_shared(this, name); ++ } ++#endif + uint32_t retryShadowBufferLimit() const override { return retry_shadow_buffer_limit_; } + const std::vector& shadowPolicies() const override { return shadow_policies_; } + const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const override { +@@ -569,6 +613,7 @@ public: + } + const VirtualHost& virtualHost() const override { return vhost_; } + bool autoHostRewrite() const override { return auto_host_rewrite_; } ++ bool appendXfh() const override { return append_xfh_; } + const std::multimap& opaqueConfig() const override { + return opaque_config_; + } +@@ -608,42 +653,13 @@ public: + const std::string& filter_name, + std::function cb) const override; + +-protected: +- const bool case_sensitive_; +- const std::string prefix_rewrite_; +- Regex::CompiledMatcherPtr regex_rewrite_; +- Regex::CompiledMatcherPtr regex_rewrite_redirect_; +- std::string regex_rewrite_substitution_; +- std::string regex_rewrite_redirect_substitution_; +- const std::string host_rewrite_; +- bool include_vh_rate_limits_; +- absl::optional connect_config_; +- +- RouteConstSharedPtr clusterEntry(const Http::HeaderMap& headers, uint64_t random_value) const; +- +- /** +- * Returns the correct path rewrite string for this route. +- * +- * The provided container may be used to store memory backing the return value +- * therefore it must outlive any use of the return value. +- */ +- const std::string& getPathRewrite(const Http::RequestHeaderMap& headers, +- absl::optional& container) const; +- +- void finalizePathHeader(Http::RequestHeaderMap& headers, absl::string_view matched_path, +- bool insert_envoy_original_path) const; +- +- absl::optional +- currentUrlPathAfterRewriteWithMatchedPath(const Http::RequestHeaderMap& headers, +- absl::string_view matched_path) const; +- +-private: +- struct RuntimeData { +- std::string fractional_runtime_key_{}; +- envoy::type::v3::FractionalPercent fractional_runtime_default_{}; +- }; +- ++#if defined(ALIMESH) ++ class DynamicRouteEntry : public RouteEntry, ++ public Route, ++ public std::enable_shared_from_this { ++#else + class DynamicRouteEntry : public RouteEntry, public Route { ++#endif + public: + DynamicRouteEntry(const RouteEntryImplBase* parent, const std::string& name) + : parent_(parent), cluster_name_(name) {} +@@ -723,6 +739,7 @@ private: + + const VirtualHost& virtualHost() const override { return parent_->virtualHost(); } + bool autoHostRewrite() const override { return parent_->autoHostRewrite(); } ++ bool appendXfh() const override { return parent_->appendXfh(); } + bool includeVirtualHostRateLimits() const override { + return parent_->includeVirtualHostRateLimits(); + } +@@ -745,6 +762,9 @@ private: + const absl::optional& connectConfig() const override { + return parent_->connectConfig(); + } ++ const RouteStatsContextOptRef routeStatsContext() const override { ++ return parent_->routeStatsContext(); ++ } + const UpgradeMap& upgradeMap() const override { return parent_->upgradeMap(); } + + // Router::Route +@@ -762,6 +782,18 @@ private: + parent_->traversePerFilterConfig(filter_name, cb); + }; + ++#if defined(ALIMESH) ++ const InternalActiveRedirectPolicy& internalActiveRedirectPolicy() const override { ++ return parent_->internalActiveRedirectPolicy(); ++ } ++ ++ RouteConstSharedPtr clone(const std::string& name) const { ++ return std::make_shared(parent_, name); ++ } ++ ++ virtual RouteConstSharedPtr getRouteConstSharedPtr() const { return shared_from_this(); } ++#endif ++ + private: + const RouteEntryImplBase* parent_; + const std::string cluster_name_; +@@ -821,6 +853,10 @@ private: + + const Http::LowerCaseString& clusterHeaderName() const { return cluster_header_name_; } + ++#if defined(ALIMESH) ++ RouteConstSharedPtr getRouteConstSharedPtr() const override { return shared_from_this(); } ++#endif ++ + private: + const std::string runtime_key_; + Runtime::Loader& loader_; +@@ -835,6 +871,64 @@ private: + + using WeightedClusterEntrySharedPtr = std::shared_ptr; + ++protected: ++ const bool case_sensitive_; ++ const std::string prefix_rewrite_; ++ Regex::CompiledMatcherPtr regex_rewrite_; ++ Regex::CompiledMatcherPtr regex_rewrite_redirect_; ++ std::string regex_rewrite_substitution_; ++ std::string regex_rewrite_redirect_substitution_; ++ const std::string host_rewrite_; ++ bool include_vh_rate_limits_; ++ absl::optional connect_config_; ++ ++ RouteConstSharedPtr clusterEntry(const Http::RequestHeaderMap& headers, ++ uint64_t random_value) const; ++ ++ /** ++ * Returns the correct path rewrite string for this route. ++ * ++ * The provided container may be used to store memory backing the return value ++ * therefore it must outlive any use of the return value. ++ */ ++ const std::string& getPathRewrite(const Http::RequestHeaderMap& headers, ++ absl::optional& container) const; ++ ++ void finalizePathHeader(Http::RequestHeaderMap& headers, absl::string_view matched_path, ++ bool insert_envoy_original_path) const; ++ ++ absl::optional ++ currentUrlPathAfterRewriteWithMatchedPath(const Http::RequestHeaderMap& headers, ++ absl::string_view matched_path) const; ++ ++private: ++ struct RuntimeData { ++ std::string fractional_runtime_key_{}; ++ envoy::type::v3::FractionalPercent fractional_runtime_default_{}; ++ }; ++ ++ /** ++ * Returns a vector of request header parsers which applied or will apply header transformations ++ * to the request in this route. ++ * @param specificity_ascend specifies whether the returned parsers will be sorted from least ++ * specific to most specific (global connection manager level header parser, virtual host ++ * level header parser and finally route-level parser.) or the reverse. ++ * @return a vector of request header parsers. ++ */ ++ absl::InlinedVector ++ getRequestHeaderParsers(bool specificity_ascend) const; ++ ++ /** ++ * Returns a vector of response header parsers which applied or will apply header transformations ++ * to the response in this route. ++ * @param specificity_ascend specifies whether the returned parsers will be sorted from least ++ * specific to most specific (global connection manager level header parser, virtual host ++ * level header parser and finally route-level parser.) or the reverse. ++ * @return a vector of request header parsers. ++ */ ++ absl::InlinedVector ++ getResponseHeaderParsers(bool specificity_ascend) const; ++ + absl::optional loadRuntimeData(const envoy::config::route::v3::RouteMatch& route); + + static std::multimap +@@ -863,6 +957,12 @@ private: + ProtobufMessage::ValidationVisitor& validator, + absl::string_view current_route_name) const; + ++#if defined(ALIMESH) ++ InternalActiveRedirectPoliciesImpl ++ buildActiveInternalRedirectPolicy(const envoy::config::route::v3::RouteAction& route_config, ++ ProtobufMessage::ValidationVisitor& validator, ++ absl::string_view current_route_name) const; ++#endif + RouteConstSharedPtr pickClusterViaClusterHeader(const Http::LowerCaseString& cluster_header_name, + const Http::HeaderMap& headers) const; + +@@ -879,8 +979,11 @@ private: + const absl::optional auto_host_rewrite_header_; + const Regex::CompiledMatcherPtr host_rewrite_path_regex_; + const std::string host_rewrite_path_regex_substitution_; ++ const bool append_xfh_; + const std::string cluster_name_; ++ RouteStatsContextPtr route_stats_context_; + const Http::LowerCaseString cluster_header_name_; ++ ClusterSpecifierPluginSharedPtr cluster_specifier_plugin_; + const Http::Code cluster_not_found_response_code_; + const std::chrono::milliseconds timeout_; + const absl::optional idle_timeout_; +@@ -933,6 +1036,10 @@ private: + PerFilterConfigs per_filter_configs_; + const std::string route_name_; + TimeSource& time_source_; ++ ++#if defined(ALIMESH) ++ const InternalActiveRedirectPoliciesImpl internal_active_redirect_policy_; ++#endif + }; + + /** +@@ -1145,6 +1252,8 @@ public: + return max_direct_response_body_size_bytes_; + } + ++ ClusterSpecifierPluginSharedPtr clusterSpecifierPlugin(absl::string_view provider) const; ++ + private: + std::unique_ptr route_matcher_; + std::list internal_only_headers_; +@@ -1155,6 +1264,9 @@ private: + const bool uses_vhds_; + const bool most_specific_header_mutations_wins_; + const uint32_t max_direct_response_body_size_bytes_; ++ ++ // Cluster specifier plugins/providers. ++ absl::flat_hash_map cluster_specifier_plugins_; + }; + + /** +diff --git a/source/common/router/context_impl.cc b/source/common/router/context_impl.cc +index 2a2df3b234..921455ce68 100644 +--- a/source/common/router/context_impl.cc ++++ b/source/common/router/context_impl.cc +@@ -1,10 +1,15 @@ + #include "source/common/router/context_impl.h" + ++#include "source/common/config/utility.h" ++ + namespace Envoy { + namespace Router { + + ContextImpl::ContextImpl(Stats::SymbolTable& symbol_table) +- : stat_names_(symbol_table), virtual_cluster_stat_names_(symbol_table) {} ++ : stat_names_(symbol_table), route_stat_names_(symbol_table), ++ virtual_cluster_stat_names_(symbol_table), ++ generic_conn_pool_factory_(Envoy::Config::Utility::getFactoryByName( ++ "envoy.filters.connection_pools.http.generic")) {} + + } // namespace Router + } // namespace Envoy +diff --git a/source/common/router/context_impl.h b/source/common/router/context_impl.h +index fd36cbdd3a..da794fde5c 100644 +--- a/source/common/router/context_impl.h ++++ b/source/common/router/context_impl.h +@@ -4,6 +4,8 @@ + #include "envoy/router/router.h" + #include "envoy/stats/stats_macros.h" + ++#include "source/common/common/assert.h" ++ + namespace Envoy { + namespace Router { + +@@ -38,10 +40,17 @@ public: + const VirtualClusterStatNames& virtualClusterStatNames() const override { + return virtual_cluster_stat_names_; + } ++ const RouteStatNames& routeStatNames() const override { return route_stat_names_; } ++ GenericConnPoolFactory& genericConnPoolFactory() override { ++ ASSERT(generic_conn_pool_factory_ != nullptr); ++ return *generic_conn_pool_factory_; ++ } + + private: + const StatNames stat_names_; ++ const RouteStatNames route_stat_names_; + const VirtualClusterStatNames virtual_cluster_stat_names_; ++ GenericConnPoolFactory* generic_conn_pool_factory_; + }; + + } // namespace Router +diff --git a/source/common/router/delegating_route_impl.cc b/source/common/router/delegating_route_impl.cc +index 422b43248d..ddf1899837 100644 +--- a/source/common/router/delegating_route_impl.cc ++++ b/source/common/router/delegating_route_impl.cc +@@ -126,6 +126,8 @@ bool DelegatingRouteEntry::autoHostRewrite() const { + return base_route_->routeEntry()->autoHostRewrite(); + } + ++bool DelegatingRouteEntry::appendXfh() const { return base_route_->routeEntry()->appendXfh(); } ++ + const MetadataMatchCriteria* DelegatingRouteEntry::metadataMatchCriteria() const { + return base_route_->routeEntry()->metadataMatchCriteria(); + } +diff --git a/source/common/router/delegating_route_impl.h b/source/common/router/delegating_route_impl.h +index f9696e8fc7..939d3094be 100644 +--- a/source/common/router/delegating_route_impl.h ++++ b/source/common/router/delegating_route_impl.h +@@ -95,6 +95,7 @@ public: + const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const override; + const VirtualHost& virtualHost() const override; + bool autoHostRewrite() const override; ++ bool appendXfh() const override; + const MetadataMatchCriteria* metadataMatchCriteria() const override; + const std::multimap& opaqueConfig() const override; + bool includeVirtualHostRateLimits() const override; +@@ -106,6 +107,12 @@ public: + const absl::optional& connectConfig() const override; + const std::string& routeName() const override; + ++#if defined(ALIMESH) ++ const InternalActiveRedirectPolicy& internalActiveRedirectPolicy() const override { ++ return base_route_->routeEntry()->internalActiveRedirectPolicy(); ++ } ++#endif ++ + private: + const Router::RouteConstSharedPtr base_route_; + }; +diff --git a/source/common/router/retry_state_impl.cc b/source/common/router/retry_state_impl.cc +index 0b7d86b2c2..ec03e34e9f 100644 +--- a/source/common/router/retry_state_impl.cc ++++ b/source/common/router/retry_state_impl.cc +@@ -17,19 +17,27 @@ + namespace Envoy { + namespace Router { + +-RetryStatePtr RetryStateImpl::create(const RetryPolicy& route_policy, +- Http::RequestHeaderMap& request_headers, +- const Upstream::ClusterInfo& cluster, +- const VirtualCluster* vcluster, Runtime::Loader& runtime, +- Random::RandomGenerator& random, Event::Dispatcher& dispatcher, +- TimeSource& time_source, Upstream::ResourcePriority priority) { +- RetryStatePtr ret; ++bool clusterSupportsHttp3AndTcpFallback(const Upstream::ClusterInfo& cluster) { ++ return (cluster.features() & Upstream::ClusterInfo::Features::HTTP3) && ++ // USE_ALPN is only set when a TCP pool is also configured. Such cluster supports TCP ++ // fallback. ++ (cluster.features() & Upstream::ClusterInfo::Features::USE_ALPN); ++} ++ ++std::unique_ptr ++RetryStateImpl::create(const RetryPolicy& route_policy, Http::RequestHeaderMap& request_headers, ++ const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, ++ RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime, ++ Random::RandomGenerator& random, Event::Dispatcher& dispatcher, ++ TimeSource& time_source, Upstream::ResourcePriority priority) { ++ std::unique_ptr ret; + + // We short circuit here and do not bother with an allocation if there is no chance we will retry. + if (request_headers.EnvoyRetryOn() || request_headers.EnvoyRetryGrpcOn() || + route_policy.retryOn()) { +- ret.reset(new RetryStateImpl(route_policy, request_headers, cluster, vcluster, runtime, random, +- dispatcher, time_source, priority)); ++ ret.reset(new RetryStateImpl(route_policy, request_headers, cluster, vcluster, ++ route_stats_context, runtime, random, dispatcher, time_source, ++ priority)); + } + + // Consume all retry related headers to avoid them being propagated to the upstream +@@ -47,13 +55,14 @@ RetryStatePtr RetryStateImpl::create(const RetryPolicy& route_policy, + RetryStateImpl::RetryStateImpl(const RetryPolicy& route_policy, + Http::RequestHeaderMap& request_headers, + const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, ++ RouteStatsContextOptRef route_stats_context, + Runtime::Loader& runtime, Random::RandomGenerator& random, + Event::Dispatcher& dispatcher, TimeSource& time_source, + Upstream::ResourcePriority priority) +- : cluster_(cluster), vcluster_(vcluster), runtime_(runtime), random_(random), +- dispatcher_(dispatcher), time_source_(time_source), retry_on_(route_policy.retryOn()), +- retries_remaining_(route_policy.numRetries()), priority_(priority), +- retry_host_predicates_(route_policy.retryHostPredicates()), ++ : cluster_(cluster), vcluster_(vcluster), route_stats_context_(route_stats_context), ++ runtime_(runtime), random_(random), dispatcher_(dispatcher), time_source_(time_source), ++ retry_on_(route_policy.retryOn()), retries_remaining_(route_policy.numRetries()), ++ priority_(priority), retry_host_predicates_(route_policy.retryHostPredicates()), + retry_priority_(route_policy.retryPriority()), + retriable_status_codes_(route_policy.retriableStatusCodes()), + retriable_headers_(route_policy.retriableHeaders()), +@@ -240,6 +249,9 @@ RetryStatus RetryStateImpl::shouldRetry(bool would_retry, DoRetryCallback callba + if (vcluster_) { + vcluster_->stats().upstream_rq_retry_success_.inc(); + } ++ if (route_stats_context_.has_value()) { ++ route_stats_context_->stats().upstream_rq_retry_success_.inc(); ++ } + } + + resetRetry(); +@@ -255,6 +267,9 @@ RetryStatus RetryStateImpl::shouldRetry(bool would_retry, DoRetryCallback callba + if (vcluster_) { + vcluster_->stats().upstream_rq_retry_limit_exceeded_.inc(); + } ++ if (route_stats_context_.has_value()) { ++ route_stats_context_->stats().upstream_rq_retry_limit_exceeded_.inc(); ++ } + return RetryStatus::NoRetryLimitExceeded; + } + +@@ -265,6 +280,9 @@ RetryStatus RetryStateImpl::shouldRetry(bool would_retry, DoRetryCallback callba + if (vcluster_) { + vcluster_->stats().upstream_rq_retry_overflow_.inc(); + } ++ if (route_stats_context_.has_value()) { ++ route_stats_context_->stats().upstream_rq_retry_overflow_.inc(); ++ } + return RetryStatus::NoOverflow; + } + +@@ -279,6 +297,10 @@ RetryStatus RetryStateImpl::shouldRetry(bool would_retry, DoRetryCallback callba + if (vcluster_) { + vcluster_->stats().upstream_rq_retry_.inc(); + } ++ if (route_stats_context_.has_value()) { ++ route_stats_context_->stats().upstream_rq_retry_.inc(); ++ } ++ + enableBackoffTimer(); + return RetryStatus::Yes; + } +diff --git a/source/common/router/retry_state_impl.h b/source/common/router/retry_state_impl.h +index affa6f9fa0..f344ad0789 100644 +--- a/source/common/router/retry_state_impl.h ++++ b/source/common/router/retry_state_impl.h +@@ -25,12 +25,12 @@ namespace Router { + */ + class RetryStateImpl : public RetryState { + public: +- static RetryStatePtr create(const RetryPolicy& route_policy, +- Http::RequestHeaderMap& request_headers, +- const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, +- Runtime::Loader& runtime, Random::RandomGenerator& random, +- Event::Dispatcher& dispatcher, TimeSource& time_source, +- Upstream::ResourcePriority priority); ++ static std::unique_ptr ++ create(const RetryPolicy& route_policy, Http::RequestHeaderMap& request_headers, ++ const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, ++ RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime, ++ Random::RandomGenerator& random, Event::Dispatcher& dispatcher, TimeSource& time_source, ++ Upstream::ResourcePriority priority); + ~RetryStateImpl() override; + + /** +@@ -94,9 +94,9 @@ public: + private: + RetryStateImpl(const RetryPolicy& route_policy, Http::RequestHeaderMap& request_headers, + const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, +- Runtime::Loader& runtime, Random::RandomGenerator& random, +- Event::Dispatcher& dispatcher, TimeSource& time_source, +- Upstream::ResourcePriority priority); ++ RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime, ++ Random::RandomGenerator& random, Event::Dispatcher& dispatcher, ++ TimeSource& time_source, Upstream::ResourcePriority priority); + + void enableBackoffTimer(); + void resetRetry(); +@@ -105,6 +105,7 @@ private: + + const Upstream::ClusterInfo& cluster_; + const VirtualCluster* vcluster_; ++ RouteStatsContextOptRef route_stats_context_; + Runtime::Loader& runtime_; + Random::RandomGenerator& random_; + Event::Dispatcher& dispatcher_; +diff --git a/source/common/router/router.cc b/source/common/router/router.cc +index 054b6a6858..aaea17c8d3 100644 +--- a/source/common/router/router.cc ++++ b/source/common/router/router.cc +@@ -42,6 +42,10 @@ + #include "source/common/stream_info/uint32_accessor_impl.h" + #include "source/common/tracing/http_tracer_impl.h" + ++#if defined(ALIMESH) ++#include "source/common/http/path_utility.h" ++#endif ++ + namespace Envoy { + namespace Router { + namespace { +@@ -298,13 +302,12 @@ Stats::StatName Filter::upstreamZone(Upstream::HostDescriptionConstSharedPtr ups + return upstream_host ? upstream_host->localityZoneStatName() : config_.empty_stat_name_; + } + +-void Filter::chargeUpstreamCode(uint64_t response_status_code, +- const Http::ResponseHeaderMap& response_headers, +- Upstream::HostDescriptionConstSharedPtr upstream_host, +- bool dropped) { +- // Passing the response_status_code explicitly is an optimization to avoid +- // multiple calls to slow Http::Utility::getResponseStatus. +- ASSERT(response_status_code == Http::Utility::getResponseStatus(response_headers)); ++#if defined(ALIMESH) ++void Filter::chargeUpstreamGrpcCode(uint64_t http_status_code, uint64_t grpc_response_code, ++ const Http::ResponseHeaderMap& response_headers, ++ Upstream::HostDescriptionConstSharedPtr upstream_host, ++ bool dropped) { ++ ASSERT(Grpc::Common::getGrpcStatus(response_headers).has_value()); + if (config_.emit_dynamic_stats_ && !callbacks_->streamInfo().healthCheck()) { + const Http::HeaderEntry* upstream_canary_header = response_headers.EnvoyUpstreamCanary(); + const bool is_canary = (upstream_canary_header && upstream_canary_header->value() == "true") || +@@ -315,11 +318,13 @@ void Filter::chargeUpstreamCode(uint64_t response_status_code, + Http::CodeStats::ResponseStatInfo info{config_.scope_, + cluster_->statsScope(), + config_.empty_stat_name_, +- response_status_code, ++ grpc_response_code, + internal_request, + route_entry_->virtualHost().statName(), + request_vcluster_ ? request_vcluster_->statName() + : config_.empty_stat_name_, ++ route_stats_context_.has_value() ? route_stats_context_->statName() ++ : config_.empty_stat_name_, + config_.zone_name_, + upstream_zone, + is_canary}; +@@ -327,6 +332,62 @@ void Filter::chargeUpstreamCode(uint64_t response_status_code, + Http::CodeStats& code_stats = httpContext().codeStats(); + code_stats.chargeResponseStat(info, exclude_http_code_stats_); + ++ if (alt_stat_prefix_ != nullptr) { ++ Http::CodeStats::ResponseStatInfo alt_info{config_.scope_, ++ cluster_->statsScope(), ++ alt_stat_prefix_->statName(), ++ grpc_response_code, ++ internal_request, ++ config_.empty_stat_name_, ++ config_.empty_stat_name_, ++ config_.empty_stat_name_, ++ config_.zone_name_, ++ upstream_zone, ++ is_canary}; ++ code_stats.chargeResponseStat(alt_info, exclude_http_code_stats_); ++ } ++ ++ if (dropped) { ++ cluster_->loadReportStats().upstream_rq_dropped_.inc(); ++ } ++ if (upstream_host && Http::CodeUtility::is5xx(http_status_code)) { ++ upstream_host->stats().rq_error_.inc(); ++ } ++ } ++} ++#endif ++ ++void Filter::chargeUpstreamCode(uint64_t response_status_code, ++ const Http::ResponseHeaderMap& response_headers, ++ Upstream::HostDescriptionConstSharedPtr upstream_host, ++ bool dropped) { ++ // Passing the response_status_code explicitly is an optimization to avoid ++ // multiple calls to slow Http::Utility::getResponseStatus. ++ ASSERT(response_status_code == Http::Utility::getResponseStatus(response_headers)); ++ if (config_.emit_dynamic_stats_ && !callbacks_->streamInfo().healthCheck()) { ++ const Http::HeaderEntry* upstream_canary_header = response_headers.EnvoyUpstreamCanary(); ++ const bool is_canary = (upstream_canary_header && upstream_canary_header->value() == "true") || ++ (upstream_host ? upstream_host->canary() : false); ++ const bool internal_request = Http::HeaderUtility::isEnvoyInternalRequest(*downstream_headers_); ++ ++ Stats::StatName upstream_zone = upstreamZone(upstream_host); ++ Http::CodeStats::ResponseStatInfo info{ ++ config_.scope_, ++ cluster_->statsScope(), ++ config_.empty_stat_name_, ++ response_status_code, ++ internal_request, ++ route_entry_->virtualHost().statName(), ++ request_vcluster_ ? request_vcluster_->statName() : config_.empty_stat_name_, ++ route_stats_context_.has_value() ? route_stats_context_->statName() ++ : config_.empty_stat_name_, ++ config_.zone_name_, ++ upstream_zone, ++ is_canary}; ++ ++ Http::CodeStats& code_stats = httpContext().codeStats(); ++ code_stats.chargeResponseStat(info, exclude_http_code_stats_); ++ + if (alt_stat_prefix_ != nullptr) { + Http::CodeStats::ResponseStatInfo alt_info{config_.scope_, + cluster_->statsScope(), +@@ -335,6 +396,7 @@ void Filter::chargeUpstreamCode(uint64_t response_status_code, + internal_request, + config_.empty_stat_name_, + config_.empty_stat_name_, ++ config_.empty_stat_name_, + config_.zone_name_, + upstream_zone, + is_canary}; +@@ -453,6 +515,10 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, + + // Set up stat prefixes, etc. + request_vcluster_ = route_entry_->virtualCluster(headers); ++ if (request_vcluster_ != nullptr) { ++ callbacks_->streamInfo().setVirtualClusterName(request_vcluster_->name()); ++ } ++ route_stats_context_ = route_entry_->routeStatsContext(); + ENVOY_STREAM_LOG(debug, "cluster '{}' match for URL '{}'", *callbacks_, + route_entry_->clusterName(), headers.getPathValue()); + +@@ -645,6 +711,15 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, + // Inject the active span's tracing context into the request headers. + callbacks_->activeSpan().injectContext(headers); + ++#if defined(ALIMESH) ++ Http::HeaderString start_time; ++ start_time.setInteger(std::chrono::duration_cast( ++ callbacks_->streamInfo().startTime().time_since_epoch()) ++ .count()); ++ downstream_headers_->setReferenceKey(Http::CustomHeaders::get().AliExtendedValues.TriStartTime, ++ start_time.getStringView()); ++#endif ++ + route_entry_->finalizeRequestHeaders(headers, callbacks_->streamInfo(), + !config_.suppress_envoy_headers_); + FilterUtility::setUpstreamScheme( +@@ -654,9 +729,10 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, + // Ensure an http transport scheme is selected before continuing with decoding. + ASSERT(headers.Scheme()); + +- retry_state_ = createRetryState( +- route_entry_->retryPolicy(), headers, *cluster_, request_vcluster_, config_.runtime_, +- config_.random_, callbacks_->dispatcher(), config_.timeSource(), route_entry_->priority()); ++ retry_state_ = ++ createRetryState(route_entry_->retryPolicy(), headers, *cluster_, request_vcluster_, ++ route_stats_context_, config_.runtime_, config_.random_, ++ callbacks_->dispatcher(), config_.timeSource(), route_entry_->priority()); + + // Determine which shadow policies to use. It's possible that we don't do any shadowing due to + // runtime keys. +@@ -697,8 +773,7 @@ Filter::createConnPool(Upstream::ThreadLocalCluster& thread_local_cluster) { + cluster_->upstreamConfig().value().DebugString())); + } + if (!factory) { +- factory = &Envoy::Config::Utility::getAndCheckFactoryByName( +- "envoy.filters.connection_pools.http.generic"); ++ factory = &config_.router_context_.genericConnPoolFactory(); + } + + bool should_tcp_proxy = false; +@@ -912,6 +987,9 @@ void Filter::onResponseTimeout() { + if (request_vcluster_) { + request_vcluster_->stats().upstream_rq_timeout_.inc(); + } ++ if (route_stats_context_.has_value()) { ++ route_stats_context_->stats().upstream_rq_timeout_.inc(); ++ } + + if (cluster_->timeoutBudgetStats().has_value()) { + // Cancel firing per-try timeout information, because the per-try timeout did not come into +@@ -1303,6 +1381,15 @@ void Filter::onUpstreamHeaders(uint64_t response_code, Http::ResponseHeaderMapPt + upstream_request.upstreamHost()->outlierDetector().putHttpResponseCode(response_code); + } + ++#if defined(ALIMESH) ++ static Envoy::Http::LowerCaseString shutdown_key("micro.service.shutdown.endpoint"); ++ if (!headers->get(shutdown_key).empty()) { ++ upstream_request.upstreamHost()->outlierDetector().forceEjectHost(); ++ ENVOY_STREAM_LOG(debug, "found shutdown header, host will be shutdown ,so forceEject this Host", ++ *callbacks_); ++ } ++#endif ++ + if (headers->EnvoyImmediateHealthCheckFail() != nullptr) { + upstream_request.upstreamHost()->healthChecker().setUnhealthy( + Upstream::HealthCheckHostMonitor::UnhealthyType::ImmediateHealthCheckFail); +@@ -1356,6 +1443,18 @@ void Filter::onUpstreamHeaders(uint64_t response_code, Http::ResponseHeaderMapPt + // next downstream. + } + ++#if defined(ALIMESH) ++ if (route_entry_->internalActiveRedirectPolicy().enabled() && ++ route_entry_->internalActiveRedirectPolicy().shouldRedirectForResponseCode( ++ static_cast(response_code)) && ++ setupActiveRedirect(*headers, upstream_request)) { ++ ENVOY_STREAM_LOG(debug, "setup active redirect", *callbacks_); ++ return; ++ // If the redirect could not be handled, fail open and let it pass to the ++ // next downstream. ++ } ++#endif ++ + // Check if we got a "bad" response, but there are still upstream requests in + // flight awaiting headers or scheduled retries. If so, exit to give them a + // chance to return before returning a response downstream. +@@ -1381,6 +1480,29 @@ void Filter::onUpstreamHeaders(uint64_t response_code, Http::ResponseHeaderMapPt + MonotonicTime response_received_time = dispatcher.timeSource().monotonicTime(); + std::chrono::milliseconds ms = std::chrono::duration_cast( + response_received_time - downstream_request_complete_time_); ++#if defined(ALIMESH) ++ std::chrono::milliseconds duration_ms = std::chrono::duration_cast( ++ response_received_time - callbacks_->streamInfo().startTimeMonotonic()); ++ Http::HeaderString cost_time; ++ cost_time.setInteger(duration_ms.count()); ++ headers->setReferenceKey(Http::CustomHeaders::get().AliExtendedValues.TriCostTime, ++ cost_time.getStringView()); ++ ++ Http::HeaderString arrive_time; ++ arrive_time.setInteger(std::chrono::duration_cast( ++ callbacks_->streamInfo().startTime().time_since_epoch()) ++ .count()); ++ headers->setReferenceKey(Http::CustomHeaders::get().AliExtendedValues.TriArriveTime, ++ arrive_time.getStringView()); ++ ++ SystemTime system_response_receive_time = dispatcher.timeSource().systemTime(); ++ Http::HeaderString start_time; ++ start_time.setInteger(std::chrono::duration_cast( ++ system_response_receive_time.time_since_epoch()) ++ .count()); ++ headers->setReferenceKey(Http::CustomHeaders::get().AliExtendedValues.TriRespStartTime, ++ start_time.getStringView()); ++#endif + if (!config_.suppress_envoy_headers_) { + headers->setEnvoyUpstreamServiceTime(ms.count()); + } +@@ -1389,7 +1511,16 @@ void Filter::onUpstreamHeaders(uint64_t response_code, Http::ResponseHeaderMapPt + upstream_request.upstreamCanary( + (headers->EnvoyUpstreamCanary() && headers->EnvoyUpstreamCanary()->value() == "true") || + upstream_request.upstreamHost()->canary()); ++#if defined(ALIMESH) ++ if (grpc_status.has_value()) { ++ chargeUpstreamGrpcCode(response_code, grpc_to_http_status, *headers, ++ upstream_request.upstreamHost(), false); ++ } else { ++ chargeUpstreamCode(response_code, *headers, upstream_request.upstreamHost(), false); ++ } ++#else + chargeUpstreamCode(response_code, *headers, upstream_request.upstreamHost(), false); ++#endif + if (!Http::CodeUtility::is5xx(response_code)) { + handleNon5xxResponseHeaders(grpc_status, upstream_request, end_stream, grpc_to_http_status); + } +@@ -1488,17 +1619,19 @@ void Filter::onUpstreamComplete(UpstreamRequest& upstream_request) { + const bool internal_request = Http::HeaderUtility::isEnvoyInternalRequest(*downstream_headers_); + + Http::CodeStats& code_stats = httpContext().codeStats(); +- Http::CodeStats::ResponseTimingInfo info{config_.scope_, +- cluster_->statsScope(), +- config_.empty_stat_name_, +- response_time, +- upstream_request.upstreamCanary(), +- internal_request, +- route_entry_->virtualHost().statName(), +- request_vcluster_ ? request_vcluster_->statName() +- : config_.empty_stat_name_, +- config_.zone_name_, +- upstreamZone(upstream_request.upstreamHost())}; ++ Http::CodeStats::ResponseTimingInfo info{ ++ config_.scope_, ++ cluster_->statsScope(), ++ config_.empty_stat_name_, ++ response_time, ++ upstream_request.upstreamCanary(), ++ internal_request, ++ route_entry_->virtualHost().statName(), ++ request_vcluster_ ? request_vcluster_->statName() : config_.empty_stat_name_, ++ route_stats_context_.has_value() ? route_stats_context_->statName() ++ : config_.empty_stat_name_, ++ config_.zone_name_, ++ upstreamZone(upstream_request.upstreamHost())}; + + code_stats.chargeResponseTiming(info); + +@@ -1511,6 +1644,7 @@ void Filter::onUpstreamComplete(UpstreamRequest& upstream_request) { + internal_request, + config_.empty_stat_name_, + config_.empty_stat_name_, ++ config_.empty_stat_name_, + config_.zone_name_, + upstreamZone(upstream_request.upstreamHost())}; + +@@ -1624,7 +1758,8 @@ bool Filter::convertRequestHeadersForInternalRedirect(Http::RequestHeaderMap& do + return false; + } + +- const auto& route_name = route->routeEntry()->routeName(); ++ const auto& route_name = route->directResponseEntry() ? route->directResponseEntry()->routeName() ++ : route->routeEntry()->routeName(); + for (const auto& predicate : policy.predicates()) { + if (!predicate->acceptTargetRoute(*filter_state, route_name, !scheme_is_http, + !target_is_http)) { +@@ -1654,6 +1789,143 @@ bool Filter::convertRequestHeadersForInternalRedirect(Http::RequestHeaderMap& do + return true; + } + ++#if defined(ALIMESH) ++bool Filter::setupActiveRedirect(const Http::ResponseHeaderMap&, UpstreamRequest&) { ++ ENVOY_STREAM_LOG(debug, "attempting internal active redirect", *callbacks_); ++ ++ std::string end_stream = downstream_end_stream_ ? "true" : "false"; ++ ENVOY_STREAM_LOG(debug, "downstream_end_stream: {}", *callbacks_, end_stream); ++ ENVOY_STREAM_LOG(debug, "!decodingBuffer: {}", *callbacks_, ++ !callbacks_->decodingBuffer() ? "true" : "false"); ++ ++ // Redirects are not supported for streaming requests yet. ++ if (downstream_end_stream_ && ++ !callbacks_->decodingBuffer() && // Redirects with body not yet supported. ++ convertRequestHeadersForInternalActiveRedirect(*downstream_headers_) && ++ callbacks_->recreateStream(nullptr)) { ++ ENVOY_STREAM_LOG(debug, "Internal active redirect success", *callbacks_); ++ cluster_->stats().upstream_internal_redirect_succeeded_total_.inc(); ++ return true; ++ } ++ ++ ENVOY_STREAM_LOG(warn, "Internal active redirect failed", *callbacks_); ++ cluster_->stats().upstream_internal_redirect_failed_total_.inc(); ++ return false; ++} ++ ++bool Filter::convertRequestHeadersForInternalActiveRedirect( ++ Http::RequestHeaderMap& downstream_headers) { ++ if (!downstream_headers.Path()) { ++ ENVOY_STREAM_LOG(warn, "There is no path in the downstream header", *callbacks_); ++ return false; ++ } ++ ++ // Make sure the redirect response contains a URL to redirect to. ++ const auto& policy = route_entry_->internalActiveRedirectPolicy(); ++ const std::string path(downstream_headers.getPathValue()); ++ absl::string_view just_path(Http::PathUtil::removeQueryAndFragment(path)); ++ std::string redirect_url = policy.redirectUrl(just_path.data()); ++ if (redirect_url.empty()) { ++ ENVOY_STREAM_LOG(warn, "The redirect is empty", *callbacks_); ++ config_.stats_.passthrough_internal_redirect_bad_location_.inc(); ++ return false; ++ } ++ ++ Http::Utility::Url absolute_url; ++ if (!absolute_url.initialize(redirect_url, false)) { ++ ENVOY_STREAM_LOG(warn, "Invalid redirect address: {}", *callbacks_, redirect_url); ++ config_.stats_.passthrough_internal_redirect_bad_location_.inc(); ++ return false; ++ } ++ ++ // Don't allow serving TLS responses over plaintext unless allowed by policy. ++ const bool scheme_is_http = schemeIsHttp(downstream_headers, *callbacks_->connection()); ++ const bool target_is_http = absolute_url.scheme() == Http::Headers::get().SchemeValues.Http; ++ if (!policy.isCrossSchemeRedirectAllowed() && scheme_is_http != target_is_http) { ++ ENVOY_STREAM_LOG(warn, "Illegal Scheme", *callbacks_); ++ config_.stats_.passthrough_internal_redirect_unsafe_scheme_.inc(); ++ return false; ++ } ++ ++ const StreamInfo::FilterStateSharedPtr& filter_state = callbacks_->streamInfo().filterState(); ++ // Make sure that performing the redirect won't result in exceeding the configured number of ++ // redirects allowed for this route. ++ if (!filter_state->hasData(NumInternalRedirectsFilterStateName)) { ++ filter_state->setData( ++ NumInternalRedirectsFilterStateName, std::make_shared(0), ++ StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Request); ++ } ++ StreamInfo::UInt32Accessor& num_internal_redirect = ++ filter_state->getDataMutable(NumInternalRedirectsFilterStateName); ++ if (num_internal_redirect.value() >= policy.maxInternalRedirects()) { ++ ENVOY_STREAM_LOG(warn, "Redirection times exceeded maximum {}", *callbacks_, ++ policy.maxInternalRedirects()); ++ config_.stats_.passthrough_internal_redirect_too_many_redirects_.inc(); ++ return false; ++ } ++ // Copy the old values, so they can be restored if the redirect fails. ++ const std::string original_host(downstream_headers.getHostValue()); ++ const std::string original_path(downstream_headers.getPathValue()); ++ const bool scheme_is_set = (downstream_headers.Scheme() != nullptr); ++ Cleanup restore_original_headers( ++ [&downstream_headers, original_host, original_path, scheme_is_set, scheme_is_http]() { ++ downstream_headers.setHost(original_host); ++ downstream_headers.setPath(original_path); ++ if (scheme_is_set) { ++ downstream_headers.setScheme(scheme_is_http ? Http::Headers::get().SchemeValues.Http ++ : Http::Headers::get().SchemeValues.Https); ++ } ++ }); ++ ++ // Replace the original scheme and path. ++ downstream_headers.setScheme(absolute_url.scheme()); ++ downstream_headers.setPath(absolute_url.pathAndQueryParams()); ++ ++ if (!policy.forcedUseOriginalHost()) { ++ // Replace the original host. ++ ENVOY_STREAM_LOG(info, "Replace the original host", *callbacks_); ++ downstream_headers.setHost(absolute_url.hostAndPort()); ++ } ++ ++ if (policy.forcedAddHeaderBeforeRouteMatcher()) { ++ policy.evaluateHeaders(downstream_headers, nullptr); ++ } ++ ++ callbacks_->clearRouteCache(); ++ const auto route = callbacks_->route(); ++ // Don't allow a redirect to a non existing route. ++ if (!route) { ++ config_.stats_.passthrough_internal_redirect_no_route_.inc(); ++ ENVOY_STREAM_LOG(warn, "The internal redirect no route", *callbacks_); ++ return false; ++ } ++ ++ const auto& route_name = route->directResponseEntry() ? route->directResponseEntry()->routeName() ++ : route->routeEntry()->routeName(); ++ for (const auto& predicate : policy.predicates()) { ++ if (!predicate->acceptTargetRoute(*filter_state, route_name, !scheme_is_http, ++ !target_is_http)) { ++ config_.stats_.passthrough_internal_redirect_predicate_.inc(); ++ ENVOY_STREAM_LOG(warn, "rejecting redirect targeting {}, by {} predicate", *callbacks_, ++ route_name, predicate->name()); ++ return false; ++ } ++ } ++ ++ if (!policy.forcedAddHeaderBeforeRouteMatcher()) { ++ policy.evaluateHeaders(downstream_headers, nullptr); ++ } ++ ++ num_internal_redirect.increment(); ++ restore_original_headers.cancel(); ++ // Preserve the original request URL for the second pass. ++ downstream_headers.setEnvoyOriginalUrl(absl::StrCat(scheme_is_http ++ ? Http::Headers::get().SchemeValues.Http ++ : Http::Headers::get().SchemeValues.Https, ++ "://", original_host, original_path)); ++ return true; ++} ++#endif + void Filter::runRetryOptionsPredicates(UpstreamRequest& retriable_request) { + for (const auto& options_predicate : route_entry_->retryPolicy().retryOptionsPredicates()) { + const Upstream::RetryOptionsPredicate::UpdateOptionsParameters parameters{ +@@ -1719,15 +1991,14 @@ uint32_t Filter::numRequestsAwaitingHeaders() { + [](const auto& req) -> bool { return req->awaitingHeaders(); }); + } + +-RetryStatePtr ProdFilter::createRetryState(const RetryPolicy& policy, +- Http::RequestHeaderMap& request_headers, +- const Upstream::ClusterInfo& cluster, +- const VirtualCluster* vcluster, Runtime::Loader& runtime, +- Random::RandomGenerator& random, +- Event::Dispatcher& dispatcher, TimeSource& time_source, +- Upstream::ResourcePriority priority) { +- return RetryStateImpl::create(policy, request_headers, cluster, vcluster, runtime, random, +- dispatcher, time_source, priority); ++RetryStatePtr ++ProdFilter::createRetryState(const RetryPolicy& policy, Http::RequestHeaderMap& request_headers, ++ const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, ++ RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime, ++ Random::RandomGenerator& random, Event::Dispatcher& dispatcher, ++ TimeSource& time_source, Upstream::ResourcePriority priority) { ++ return RetryStateImpl::create(policy, request_headers, cluster, vcluster, route_stats_context, ++ runtime, random, dispatcher, time_source, priority); + } + + } // namespace Router +diff --git a/source/common/router/router.h b/source/common/router/router.h +index e9d0234aed..92425f23e1 100644 +--- a/source/common/router/router.h ++++ b/source/common/router/router.h +@@ -35,6 +35,10 @@ + #include "source/common/stream_info/stream_info_impl.h" + #include "source/common/upstream/load_balancer_impl.h" + ++#if defined(ALIMESH) ++#include "envoy/stats/timespan.h" ++#endif ++ + namespace Envoy { + namespace Router { + +@@ -188,8 +192,8 @@ public: + const Protobuf::RepeatedPtrField& strict_check_headers, + TimeSource& time_source, Http::Context& http_context, + Router::Context& router_context) +- : scope_(scope), local_info_(local_info), cm_(cm), runtime_(runtime), random_(random), +- stats_(router_context.statNames(), scope, stat_prefix), ++ : router_context_(router_context), scope_(scope), local_info_(local_info), cm_(cm), ++ runtime_(runtime), random_(random), stats_(router_context_.statNames(), scope, stat_prefix), + emit_dynamic_stats_(emit_dynamic_stats), start_child_span_(start_child_span), + suppress_envoy_headers_(suppress_envoy_headers), + respect_expected_rq_timeout_(respect_expected_rq_timeout), +@@ -224,6 +228,7 @@ public: + ShadowWriter& shadowWriter() { return *shadow_writer_; } + TimeSource& timeSource() { return time_source_; } + ++ Router::Context& router_context_; + Stats::Scope& scope_; + const LocalInfo::LocalInfo& local_info_; + Upstream::ClusterManager& cm_; +@@ -286,7 +291,8 @@ public: + virtual bool downstreamEndStream() const PURE; + virtual uint32_t attemptCount() const PURE; + virtual const VirtualCluster* requestVcluster() const PURE; +- virtual const RouteEntry* routeEntry() const PURE; ++ virtual const RouteStatsContextOptRef routeStatsContext() const PURE; ++ virtual const Route* route() const PURE; + virtual const std::list& upstreamRequests() const PURE; + virtual const UpstreamRequest* finalUpstreamRequest() const PURE; + virtual TimeSource& timeSource() PURE; +@@ -462,7 +468,8 @@ public: + bool downstreamEndStream() const override { return downstream_end_stream_; } + uint32_t attemptCount() const override { return attempt_count_; } + const VirtualCluster* requestVcluster() const override { return request_vcluster_; } +- const RouteEntry* routeEntry() const override { return route_entry_; } ++ const RouteStatsContextOptRef routeStatsContext() const override { return route_stats_context_; } ++ const Route* route() const override { return route_.get(); } + const std::list& upstreamRequests() const override { + return upstream_requests_; + } +@@ -475,6 +482,11 @@ private: + void onPerTryTimeoutCommon(UpstreamRequest& upstream_request, Stats::Counter& error_counter, + const std::string& response_code_details); + Stats::StatName upstreamZone(Upstream::HostDescriptionConstSharedPtr upstream_host); ++#if defined(ALIMESH) ++ void chargeUpstreamGrpcCode(uint64_t http_status_code, uint64_t grpc_response_code, ++ const Http::ResponseHeaderMap& response_headers, ++ Upstream::HostDescriptionConstSharedPtr upstream_host, bool dropped); ++#endif + void chargeUpstreamCode(uint64_t response_status_code, + const Http::ResponseHeaderMap& response_headers, + Upstream::HostDescriptionConstSharedPtr upstream_host, bool dropped); +@@ -482,13 +494,12 @@ private: + bool dropped); + void chargeUpstreamAbort(Http::Code code, bool dropped, UpstreamRequest& upstream_request); + void cleanup(); +- virtual RetryStatePtr createRetryState(const RetryPolicy& policy, +- Http::RequestHeaderMap& request_headers, +- const Upstream::ClusterInfo& cluster, +- const VirtualCluster* vcluster, Runtime::Loader& runtime, +- Random::RandomGenerator& random, +- Event::Dispatcher& dispatcher, TimeSource& time_source, +- Upstream::ResourcePriority priority) PURE; ++ virtual RetryStatePtr ++ createRetryState(const RetryPolicy& policy, Http::RequestHeaderMap& request_headers, ++ const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, ++ RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime, ++ Random::RandomGenerator& random, Event::Dispatcher& dispatcher, ++ TimeSource& time_source, Upstream::ResourcePriority priority) PURE; + + std::unique_ptr + createConnPool(Upstream::ThreadLocalCluster& thread_local_cluster); +@@ -532,6 +543,12 @@ private: + uint64_t grpc_to_http_status); + Http::Context& httpContext() { return config_.http_context_; } + ++#if defined(ALIMESH) ++ bool setupActiveRedirect(const Http::ResponseHeaderMap& headers, ++ UpstreamRequest& upstream_request); ++ bool convertRequestHeadersForInternalActiveRedirect(Http::RequestHeaderMap& downstream_headers); ++#endif ++ + RetryStatePtr retry_state_; + FilterConfig& config_; + Http::StreamDecoderFilterCallbacks* callbacks_{}; +@@ -540,6 +557,7 @@ private: + Upstream::ClusterInfoConstSharedPtr cluster_; + std::unique_ptr alt_stat_prefix_; + const VirtualCluster* request_vcluster_; ++ RouteStatsContextOptRef route_stats_context_; + Event::TimerPtr response_timeout_; + FilterUtility::TimeoutData timeout_; + FilterUtility::HedgingParams hedging_params_; +@@ -584,9 +602,10 @@ private: + // Filter + RetryStatePtr createRetryState(const RetryPolicy& policy, Http::RequestHeaderMap& request_headers, + const Upstream::ClusterInfo& cluster, +- const VirtualCluster* vcluster, Runtime::Loader& runtime, +- Random::RandomGenerator& random, Event::Dispatcher& dispatcher, +- TimeSource& time_source, ++ const VirtualCluster* vcluster, ++ RouteStatsContextOptRef route_stats_context, ++ Runtime::Loader& runtime, Random::RandomGenerator& random, ++ Event::Dispatcher& dispatcher, TimeSource& time_source, + Upstream::ResourcePriority priority) override; + }; + +diff --git a/source/common/router/upstream_request.cc b/source/common/router/upstream_request.cc +index 147f7af49f..80792d9a81 100644 +--- a/source/common/router/upstream_request.cc ++++ b/source/common/router/upstream_request.cc +@@ -207,7 +207,7 @@ void UpstreamRequest::dumpState(std::ostream& os, int indent_level) const { + DUMP_DETAILS(request_headers); + } + +-const RouteEntry& UpstreamRequest::routeEntry() const { return *parent_.routeEntry(); } ++const Route& UpstreamRequest::route() const { return *parent_.route(); } + + const Network::Connection& UpstreamRequest::connection() const { + return *parent_.callbacks()->connection(); +@@ -425,6 +425,12 @@ void UpstreamRequest::onPoolReady( + // here. + parent_.requestVcluster()->stats().upstream_rq_total_.inc(); + } ++ if (parent_.routeStatsContext().has_value()) { ++ // The cluster increases its upstream_rq_total_ counter right before firing this onPoolReady ++ // callback. Hence, the upstream request increases the route level upstream_rq_total_ stat ++ // here. ++ parent_.routeStatsContext()->stats().upstream_rq_total_.inc(); ++ } + + host->outlierDetector().putResult(Upstream::Outlier::Result::LocalOriginConnectSuccess); + +@@ -465,12 +471,23 @@ void UpstreamRequest::onPoolReady( + + calling_encode_headers_ = true; + auto* headers = parent_.downstreamHeaders(); +- if (parent_.routeEntry()->autoHostRewrite() && !host->hostname().empty()) { +- parent_.downstreamHeaders()->setHost(host->hostname()); ++ const auto* route_entry = parent_.route()->routeEntry(); ++ if (route_entry->autoHostRewrite() && !host->hostname().empty()) { ++ Http::Utility::updateAuthority(*parent_.downstreamHeaders(), host->hostname(), ++ route_entry->appendXfh()); + } + + if (span_ != nullptr) { + span_->injectContext(*parent_.downstreamHeaders()); ++ ++#if defined(ALIMESH) ++ const std::string& address = host->address()->ip()->addressAsString(); ++ if (host->address()->ip()->version() == Network::Address::IpVersion::v6) { ++ span_->setTag(Tracing::Tags::get().PeerIpv6, address); ++ } else { ++ span_->setTag(Tracing::Tags::get().PeerIpv4, address); ++ } ++#endif + } + + upstream_timing_.onFirstUpstreamTxByteSent(parent_.callbacks()->dispatcher().timeSource()); +diff --git a/source/common/router/upstream_request.h b/source/common/router/upstream_request.h +index 98f214c0d2..bd033f8084 100644 +--- a/source/common/router/upstream_request.h ++++ b/source/common/router/upstream_request.h +@@ -65,7 +65,7 @@ public: + void onAboveWriteBufferHighWatermark() override { disableDataFromDownstreamForFlowControl(); } + void onBelowWriteBufferLowWatermark() override { enableDataFromDownstreamForFlowControl(); } + // UpstreamToDownstream +- const RouteEntry& routeEntry() const override; ++ const Route& route() const override; + const Network::Connection& connection() const override; + + void disableDataFromDownstreamForFlowControl(); +diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc +index 945a5ff122..81ee0d4d95 100644 +--- a/source/common/runtime/runtime_features.cc ++++ b/source/common/runtime/runtime_features.cc +@@ -90,6 +90,7 @@ constexpr const char* runtime_features[] = { + "envoy.reloadable_features.strip_port_from_connect", + "envoy.reloadable_features.treat_host_like_authority", + "envoy.reloadable_features.treat_upstream_connect_timeout_as_connect_failure", ++ "envoy.reloadable_features.skip_delay_close", + "envoy.reloadable_features.udp_listener_updates_filter_chain_in_place", + "envoy.reloadable_features.udp_per_event_loop_read_limit", + "envoy.reloadable_features.unquote_log_string_values", +diff --git a/source/common/stream_info/stream_info_impl.h b/source/common/stream_info/stream_info_impl.h +index 5abd0c7261..6ce2afe773 100644 +--- a/source/common/stream_info/stream_info_impl.h ++++ b/source/common/stream_info/stream_info_impl.h +@@ -187,6 +187,14 @@ struct StreamInfoImpl : public StreamInfo { + + const std::string& getRouteName() const override { return route_name_; } + ++ void setVirtualClusterName(const absl::optional& virtual_cluster_name) override { ++ virtual_cluster_name_ = virtual_cluster_name; ++ } ++ ++ const absl::optional& virtualClusterName() const override { ++ return virtual_cluster_name_; ++ } ++ + void setUpstreamLocalAddress( + const Network::Address::InstanceConstSharedPtr& upstream_local_address) override { + upstream_local_address_ = upstream_local_address; +@@ -306,6 +314,9 @@ struct StreamInfoImpl : public StreamInfo { + std::string route_name_; + absl::optional upstream_connection_id_; + absl::optional attempt_count_; ++ // TODO(agrawroh): Check if the owner of this storage outlives the StreamInfo. We should only copy ++ // the string if it could outlive the StreamInfo. ++ absl::optional virtual_cluster_name_; + + private: + static Network::ConnectionInfoProviderSharedPtr emptyDownstreamAddressProvider() { +diff --git a/source/common/thread_local/thread_local_impl.h b/source/common/thread_local/thread_local_impl.h +index 26c08dfce3..69b159bea3 100644 +--- a/source/common/thread_local/thread_local_impl.h ++++ b/source/common/thread_local/thread_local_impl.h +@@ -47,6 +47,7 @@ private: + void runOnAllThreads(const UpdateCb& cb, const Event::PostCb& complete_cb) override; + bool currentThreadRegistered() override; + void set(InitializeCb cb) override; ++ bool isShutdown() const override { return parent_.shutdown_; } + + InstanceImpl& parent_; + const uint32_t index_; +diff --git a/source/common/tracing/http_tracer_impl.cc b/source/common/tracing/http_tracer_impl.cc +index 84e7168a68..e55cf00e0a 100644 +--- a/source/common/tracing/http_tracer_impl.cc ++++ b/source/common/tracing/http_tracer_impl.cc +@@ -277,6 +277,17 @@ SpanPtr HttpTracerImpl::startSpan(const Config& config, Http::RequestHeaderMap& + if (active_span) { + active_span->setTag(Tracing::Tags::get().NodeId, local_info_.nodeName()); + active_span->setTag(Tracing::Tags::get().Zone, local_info_.zoneName()); ++ ++#if defined(ALIMESH) ++ const std::string& remote_address = ++ stream_info.downstreamAddressProvider().localAddress()->ip()->addressAsString(); ++ if (stream_info.downstreamAddressProvider().localAddress()->ip()->version() == ++ Network::Address::IpVersion::v6) { ++ active_span->setTag(Tracing::Tags::get().PeerIpv6, remote_address); ++ } else { ++ active_span->setTag(Tracing::Tags::get().PeerIpv4, remote_address); ++ } ++#endif + } + + return active_span; +diff --git a/source/common/upstream/health_checker_impl.cc b/source/common/upstream/health_checker_impl.cc +index 09d8ebeca4..998e4c2ef5 100644 +--- a/source/common/upstream/health_checker_impl.cc ++++ b/source/common/upstream/health_checker_impl.cc +@@ -546,7 +546,18 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onInterval() { + client_->addReadFilter(session_callbacks_); + + expect_close_ = false; ++#if defined(ALIMESH) ++ try { ++ client_->connect(); ++ } catch (const EnvoyException& ex) { ++ ENVOY_CONN_LOG(critical, ++ "envoy exception raised in TcpActiveHealthCheckSession::onInterval(): {}", ++ *client_, ex.what()); ++ return; ++ } ++#else + client_->connect(); ++#endif + client_->noDelay(true); + } + +diff --git a/source/common/upstream/outlier_detection_impl.cc b/source/common/upstream/outlier_detection_impl.cc +index bbf52ae4bc..183e6ab223 100644 +--- a/source/common/upstream/outlier_detection_impl.cc ++++ b/source/common/upstream/outlier_detection_impl.cc +@@ -64,6 +64,17 @@ void DetectorHostMonitorImpl::updateCurrentSuccessRateBucket() { + local_origin_sr_monitor_.updateCurrentSuccessRateBucket(); + } + ++#if defined(ALIMESH) ++void DetectorHostMonitorImpl::forceEjectHost() { ++ std::shared_ptr detector = detector_.lock(); ++ if (!detector) { ++ // It's possible for the cluster/detector to go away while we still have a host in use. ++ return; ++ } ++ detector->onConsecutive5xx(host_.lock()); ++} ++#endif ++ + void DetectorHostMonitorImpl::putHttpResponseCode(uint64_t response_code) { + external_origin_sr_monitor_.incTotalReqCounter(); + if (Http::CodeUtility::is5xx(response_code)) { +diff --git a/source/common/upstream/outlier_detection_impl.h b/source/common/upstream/outlier_detection_impl.h +index 76fd2efe1a..caee2050be 100644 +--- a/source/common/upstream/outlier_detection_impl.h ++++ b/source/common/upstream/outlier_detection_impl.h +@@ -42,6 +42,10 @@ public: + const absl::optional& lastUnejectionTime() override { return time_; } + double successRate(SuccessRateMonitorType) const override { return -1; } + ++#if defined(ALIMESH) ++ void forceEjectHost() override {} ++#endif ++ + private: + const absl::optional time_{}; + }; +@@ -183,6 +187,10 @@ public: + void localOriginFailure(); + void localOriginNoFailure(); + ++#if defined(ALIMESH) ++ void forceEjectHost() override; ++#endif ++ + private: + std::weak_ptr detector_; + std::weak_ptr host_; +diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc +index ab0e0c76a4..438001bb7d 100644 +--- a/source/common/upstream/upstream_impl.cc ++++ b/source/common/upstream/upstream_impl.cc +@@ -805,6 +805,7 @@ ClusterInfoImpl::ClusterInfoImpl( + factory_context.clusterManager().clusterCircuitBreakersStatNames()), + maintenance_mode_runtime_key_(absl::StrCat("upstream.maintenance_mode.", name_)), + source_address_(getSourceAddress(config, bind_config)), ++ lb_round_robin_config_(config.round_robin_lb_config()), + lb_least_request_config_(config.least_request_lb_config()), + lb_ring_hash_config_(config.ring_hash_lb_config()), + lb_maglev_config_(config.maglev_lb_config()), +diff --git a/source/exe/BUILD b/source/exe/BUILD +index f3fb551eb8..e4cef50276 100644 +--- a/source/exe/BUILD ++++ b/source/exe/BUILD +@@ -9,7 +9,7 @@ load( + "envoy_package", + ) + load("//source/extensions:all_extensions.bzl", "envoy_all_core_extensions", "envoy_all_extensions") +-load("//bazel:repositories.bzl", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") ++load("//bazel:repositories.bzl", "DARWIN_SKIP_TARGETS", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") + + licenses(["notice"]) # Apache 2 + +@@ -40,6 +40,7 @@ envoy_cc_library( + ] + select({ + "//bazel:windows_x86_64": envoy_all_extensions(WINDOWS_SKIP_TARGETS), + "//bazel:linux_ppc": envoy_all_extensions(PPC_SKIP_TARGETS), ++ "//bazel:darwin": envoy_all_extensions(DARWIN_SKIP_TARGETS), + "//conditions:default": envoy_all_extensions(), + }), + ) +diff --git a/source/extensions/common/wasm/context.cc b/source/extensions/common/wasm/context.cc +index 07447110f2..9279360508 100644 +--- a/source/extensions/common/wasm/context.cc ++++ b/source/extensions/common/wasm/context.cc +@@ -433,6 +433,12 @@ Context::findValue(absl::string_view name, Protobuf::Arena* arena, bool last) co + using google::api::expr::runtime::CelProtoWrapper; + using google::api::expr::runtime::CelValue; + ++#if defined(ALIMESH) ++ Envoy::Http::StreamFilterCallbacks* filter_callbacks = decoder_callbacks_; ++ if (filter_callbacks == nullptr) { ++ filter_callbacks = encoder_callbacks_; ++ } ++#endif + const StreamInfo::StreamInfo* info = getConstRequestStreamInfo(); + + // Convert into a dense token to enable a jump table implementation. +@@ -546,6 +552,21 @@ Context::findValue(absl::string_view name, Protobuf::Arena* arena, bool last) co + } + break; + case PropertyToken::ROUTE_NAME: ++#if defined(ALIMESH) ++ if (filter_callbacks) { ++ auto route = filter_callbacks->route(); ++ if (route) { ++ auto route_entry = route->routeEntry(); ++ if (route_entry) { ++ return CelValue::CreateString(&route_entry->routeName()); ++ } ++ auto dr_entry = route->directResponseEntry(); ++ if (dr_entry) { ++ return CelValue::CreateString(&dr_entry->routeName()); ++ } ++ } ++ } ++#endif + if (info) { + return CelValue::CreateString(&info->getRouteName()); + } +diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl +index 7e220b0a4a..b52ab543bb 100644 +--- a/source/extensions/extensions_build_config.bzl ++++ b/source/extensions/extensions_build_config.bzl +@@ -184,6 +184,8 @@ EXTENSIONS = { + "envoy.tracers.datadog": "//source/extensions/tracers/datadog:config", + "envoy.tracers.zipkin": "//source/extensions/tracers/zipkin:config", + "envoy.tracers.opencensus": "//source/extensions/tracers/opencensus:config", ++ ++ # WiP + "envoy.tracers.xray": "//source/extensions/tracers/xray:config", + "envoy.tracers.skywalking": "//source/extensions/tracers/skywalking:config", + +diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml +index d8cec006bd..d57e869c1c 100644 +--- a/source/extensions/extensions_metadata.yaml ++++ b/source/extensions/extensions_metadata.yaml +@@ -594,6 +594,11 @@ envoy.tracers.opencensus: + - envoy.tracers + security_posture: robust_to_untrusted_downstream + status: stable ++envoy.tracers.opentelemetry: ++ categories: ++ - envoy.tracers ++ security_posture: unknown ++ status: wip + envoy.tracers.skywalking: + categories: + - envoy.tracers +diff --git a/source/extensions/filters/common/ext_authz/ext_authz.h b/source/extensions/filters/common/ext_authz/ext_authz.h +index 96545dd83a..5792ed1596 100644 +--- a/source/extensions/filters/common/ext_authz/ext_authz.h ++++ b/source/extensions/filters/common/ext_authz/ext_authz.h +@@ -43,6 +43,10 @@ public: + const Http::LowerCaseString EnvoyAuthPartialBody{absl::StrCat(prefix(), "-auth-partial-body")}; + const Http::LowerCaseString EnvoyAuthHeadersToRemove{ + absl::StrCat(prefix(), "-auth-headers-to-remove")}; ++ ++#if defined(ALIMESH) ++ const Http::LowerCaseString XMseExternalAuthzCheckResult{"x-mse-external-authz-check-result"}; ++#endif + }; + + using Headers = ConstSingleton; +diff --git a/source/extensions/filters/common/ext_authz/ext_authz_http_impl.cc b/source/extensions/filters/common/ext_authz/ext_authz_http_impl.cc +index 3cf233d661..e515d6f103 100644 +--- a/source/extensions/filters/common/ext_authz/ext_authz_http_impl.cc ++++ b/source/extensions/filters/common/ext_authz/ext_authz_http_impl.cc +@@ -8,6 +8,7 @@ + #include "source/common/common/enum_to_int.h" + #include "source/common/common/fmt.h" + #include "source/common/common/matchers.h" ++#include "source/common/common/utility.h" + #include "source/common/http/async_client_impl.h" + #include "source/common/http/codes.h" + #include "source/common/runtime/runtime_features.h" +@@ -308,6 +309,26 @@ void RawHttpClientImpl::onBeforeFinalizeUpstreamSpan( + } + } + ++#if defined(ALIMESH) ++bool isAuthorizationPass(const Http::ResponseHeaderMap& headers) { ++ const uint64_t status_code = Http::Utility::getResponseStatus(headers); ++ ++ // The HTTP status code is first condition. ++ if (status_code != enumToInt(Http::Code::OK)) { ++ return false; ++ } ++ ++ const auto& get_result = headers.get(Headers::get().XMseExternalAuthzCheckResult); ++ // If x-mse-external-authz-check-result doesn't exist or has more than one value, ++ // we think this case is allowed. ++ if (get_result.size() != 1) { ++ return true; ++ } ++ ++ return absl::EqualsIgnoreCase(StringUtil::trim(get_result[0]->value().getStringView()), "true"); ++} ++#endif ++ + ResponsePtr RawHttpClientImpl::toResponse(Http::ResponseMessagePtr message) { + const uint64_t status_code = Http::Utility::getResponseStatus(message->headers()); + +@@ -344,7 +365,11 @@ ResponsePtr RawHttpClientImpl::toResponse(Http::ResponseMessagePtr message) { + message->headers().remove(storage_header_name); + + // Create an Ok authorization response. ++#if !defined(ALIMESH) + if (status_code == enumToInt(Http::Code::OK)) { ++#else ++ if (isAuthorizationPass(message->headers())) { ++#endif + SuccessResponse ok{message->headers(), + config_->upstreamHeaderMatchers(), + config_->upstreamHeaderToAppendMatchers(), +diff --git a/source/extensions/filters/common/ext_authz/ext_authz_http_impl.h b/source/extensions/filters/common/ext_authz/ext_authz_http_impl.h +index a517bef948..c485e68d1c 100644 +--- a/source/extensions/filters/common/ext_authz/ext_authz_http_impl.h ++++ b/source/extensions/filters/common/ext_authz/ext_authz_http_impl.h +@@ -155,6 +155,10 @@ private: + + using ClientConfigSharedPtr = std::shared_ptr; + ++#if defined(ALIMESH) ++bool isAuthorizationPass(const Http::ResponseHeaderMap& headers); ++#endif ++ + /** + * This client implementation is used when the Ext_Authz filter needs to communicate with an + * HTTP authorization server. Unlike the gRPC client that allows the server to define the +diff --git a/source/extensions/filters/http/cors/cors_filter.cc b/source/extensions/filters/http/cors/cors_filter.cc +index c7314a437a..1f260c3392 100644 +--- a/source/extensions/filters/http/cors/cors_filter.cc ++++ b/source/extensions/filters/http/cors/cors_filter.cc +@@ -19,6 +19,8 @@ struct HttpResponseCodeDetailValues { + }; + using HttpResponseCodeDetails = ConstSingleton; + ++Http::RegisterCustomInlineHeader ++ access_control_request_headers_handle(Http::CustomHeaders::get().AccessControlRequestHeaders); + Http::RegisterCustomInlineHeader + access_control_request_method_handle(Http::CustomHeaders::get().AccessControlRequestMethod); + Http::RegisterCustomInlineHeader +@@ -97,12 +99,26 @@ Http::FilterHeadersStatus CorsFilter::decodeHeaders(Http::RequestHeaderMap& head + Http::CustomHeaders::get().CORSValues.True); + } + +- if (!allowMethods().empty()) { +- response_headers->setInline(access_control_allow_methods_handle.handle(), allowMethods()); ++ const absl::string_view allow_methods = allowMethods(); ++ if (!allow_methods.empty()) { ++ if (allow_methods == "*") { ++ response_headers->setInline( ++ access_control_allow_methods_handle.handle(), ++ headers.getInlineValue(access_control_request_method_handle.handle())); ++ } else { ++ response_headers->setInline(access_control_allow_methods_handle.handle(), allow_methods); ++ } + } + +- if (!allowHeaders().empty()) { +- response_headers->setInline(access_control_allow_headers_handle.handle(), allowHeaders()); ++ const absl::string_view allow_headers = allowHeaders(); ++ if (!allow_headers.empty()) { ++ if (allow_headers == "*") { ++ response_headers->setInline( ++ access_control_allow_headers_handle.handle(), ++ headers.getInlineValue(access_control_request_headers_handle.handle())); ++ } else { ++ response_headers->setInline(access_control_allow_headers_handle.handle(), allow_headers); ++ } + } + + if (!maxAge().empty()) { +diff --git a/source/extensions/filters/http/ext_authz/ext_authz.cc b/source/extensions/filters/http/ext_authz/ext_authz.cc +index 90df75ee27..cd4ee8923f 100644 +--- a/source/extensions/filters/http/ext_authz/ext_authz.cc ++++ b/source/extensions/filters/http/ext_authz/ext_authz.cc +@@ -311,6 +311,7 @@ void Filter::onComplete(Filters::Common::ExtAuthz::ResponsePtr&& response) { + empty_stat_name, + empty_stat_name, + empty_stat_name, ++ empty_stat_name, + false}; + config_->httpContext().codeStats().chargeResponseStat(info, false); + } +diff --git a/source/extensions/filters/http/ratelimit/ratelimit.cc b/source/extensions/filters/http/ratelimit/ratelimit.cc +index c007471d77..5d3e19fdf4 100644 +--- a/source/extensions/filters/http/ratelimit/ratelimit.cc ++++ b/source/extensions/filters/http/ratelimit/ratelimit.cc +@@ -174,6 +174,7 @@ void Filter::complete(Filters::Common::RateLimit::LimitStatus status, + empty_stat_name, + empty_stat_name, + empty_stat_name, ++ empty_stat_name, + false}; + httpContext().codeStats().chargeResponseStat(info, false); + if (config_->enableXEnvoyRateLimitedHeader()) { +diff --git a/source/extensions/filters/http/wasm/wasm_filter.h b/source/extensions/filters/http/wasm/wasm_filter.h +index 8032153dd1..a01b86a9db 100644 +--- a/source/extensions/filters/http/wasm/wasm_filter.h ++++ b/source/extensions/filters/http/wasm/wasm_filter.h +@@ -28,7 +28,13 @@ public: + + std::shared_ptr createFilter() { + Wasm* wasm = nullptr; ++ if (!tls_slot_->currentThreadRegistered()) { ++ return nullptr; ++ } + PluginHandleSharedPtr handle = tls_slot_->get()->handle(); ++ if (!handle) { ++ return nullptr; ++ } + if (handle->wasmHandle()) { + wasm = handle->wasmHandle()->wasm().get(); + } +diff --git a/source/extensions/filters/network/http_connection_manager/config.h b/source/extensions/filters/network/http_connection_manager/config.h +index e480599fef..3464659a14 100644 +--- a/source/extensions/filters/network/http_connection_manager/config.h ++++ b/source/extensions/filters/network/http_connection_manager/config.h +@@ -39,7 +39,7 @@ namespace Extensions { + namespace NetworkFilters { + namespace HttpConnectionManager { + +-using FilterConfigProviderManager = Filter::FilterConfigProviderManager; ++using FilterConfigProviderManager = Filter::FilterConfigProviderManager; + + /** + * Config registration for the HTTP connection manager filter. @see NamedNetworkFilterConfigFactory. +@@ -125,7 +125,7 @@ public: + + // Http::FilterChainFactory + void createFilterChain(Http::FilterChainFactoryCallbacks& callbacks) override; +- using FilterFactoriesList = std::list; ++ using FilterFactoriesList = std::list>; + struct FilterConfig { + std::unique_ptr filter_factories; + bool allow_upgrade; +diff --git a/source/extensions/tracers/common/BUILD b/source/extensions/tracers/common/BUILD +index 89e447c456..d7610929c7 100644 +--- a/source/extensions/tracers/common/BUILD ++++ b/source/extensions/tracers/common/BUILD +@@ -11,6 +11,7 @@ envoy_extension_package() + envoy_cc_library( + name = "factory_base_lib", + hdrs = ["factory_base.h"], ++ visibility = ["//visibility:public"], + deps = [ + "//envoy/server:tracer_config_interface", + "//source/common/config:utility_lib", +diff --git a/source/extensions/tracers/skywalking/skywalking_stats.h b/source/extensions/tracers/skywalking/skywalking_stats.h +index 9646299eb6..1517cc1622 100644 +--- a/source/extensions/tracers/skywalking/skywalking_stats.h ++++ b/source/extensions/tracers/skywalking/skywalking_stats.h +@@ -17,6 +17,8 @@ struct SkyWalkingTracerStats { + SKYWALKING_TRACER_STATS(GENERATE_COUNTER_STRUCT) + }; + ++using SkyWalkingTracerStatsSharedPtr = std::shared_ptr; ++ + } // namespace SkyWalking + } // namespace Tracers + } // namespace Extensions +diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc +index 81489fc2ff..2f3c8432b9 100644 +--- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc ++++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc +@@ -28,8 +28,9 @@ using cpp2sky::TracerException; + + Driver::Driver(const envoy::config::trace::v3::SkyWalkingConfig& proto_config, + Server::Configuration::TracerFactoryContext& context) +- : tracing_stats_{SKYWALKING_TRACER_STATS( +- POOL_COUNTER_PREFIX(context.serverFactoryContext().scope(), "tracing.skywalking."))}, ++ : tracing_stats_(std::make_shared( ++ SkyWalkingTracerStats{SKYWALKING_TRACER_STATS(POOL_COUNTER_PREFIX( ++ context.serverFactoryContext().scope(), "tracing.skywalking."))})), + tls_slot_ptr_(context.serverFactoryContext().threadLocal().allocateSlot()) { + loadConfig(proto_config.client_config(), context.serverFactoryContext()); + tracing_context_factory_ = std::make_unique(config_); +diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.h b/source/extensions/tracers/skywalking/skywalking_tracer_impl.h +index 433c92706e..58849667b1 100644 +--- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.h ++++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.h +@@ -43,7 +43,7 @@ private: + }; + + TracerConfig config_; +- SkyWalkingTracerStats tracing_stats_; ++ SkyWalkingTracerStatsSharedPtr tracing_stats_; + ThreadLocal::SlotPtr tls_slot_ptr_; + std::unique_ptr tracing_context_factory_; + }; +diff --git a/source/extensions/tracers/skywalking/trace_segment_reporter.cc b/source/extensions/tracers/skywalking/trace_segment_reporter.cc +index c3ecda817d..fe3a5cb45b 100644 +--- a/source/extensions/tracers/skywalking/trace_segment_reporter.cc ++++ b/source/extensions/tracers/skywalking/trace_segment_reporter.cc +@@ -17,7 +17,7 @@ Http::RegisterCustomInlineHeadercreateUncachedRawAsyncClient()), + service_method_(*Protobuf::DescriptorPool::generated_pool()->FindMethodByName( +@@ -48,14 +48,14 @@ void TraceSegmentReporter::report(TracingContextPtr tracing_context) { + ENVOY_LOG(trace, "Try to report segment to SkyWalking Server:\n{}", request.DebugString()); + + if (stream_ != nullptr) { +- tracing_stats_.segments_sent_.inc(); ++ tracing_stats_->segments_sent_.inc(); + stream_->sendMessage(request, false); + return; + } + // Null stream_ and cache segment data temporarily. + delayed_segments_cache_.emplace(request); + if (delayed_segments_cache_.size() > delayed_buffer_size_) { +- tracing_stats_.segments_dropped_.inc(); ++ tracing_stats_->segments_dropped_.inc(); + delayed_segments_cache_.pop(); + } + } +@@ -63,12 +63,12 @@ void TraceSegmentReporter::report(TracingContextPtr tracing_context) { + void TraceSegmentReporter::flushTraceSegments() { + ENVOY_LOG(debug, "Flush segments in cache to SkyWalking backend service"); + while (!delayed_segments_cache_.empty() && stream_ != nullptr) { +- tracing_stats_.segments_sent_.inc(); +- tracing_stats_.segments_flushed_.inc(); ++ tracing_stats_->segments_sent_.inc(); ++ tracing_stats_->segments_flushed_.inc(); + stream_->sendMessage(delayed_segments_cache_.front(), false); + delayed_segments_cache_.pop(); + } +- tracing_stats_.cache_flushed_.inc(); ++ tracing_stats_->cache_flushed_.inc(); + } + + void TraceSegmentReporter::closeStream() { +diff --git a/source/extensions/tracers/skywalking/trace_segment_reporter.h b/source/extensions/tracers/skywalking/trace_segment_reporter.h +index db198d2e0c..2fb5a07188 100644 +--- a/source/extensions/tracers/skywalking/trace_segment_reporter.h ++++ b/source/extensions/tracers/skywalking/trace_segment_reporter.h +@@ -23,7 +23,7 @@ class TraceSegmentReporter : public Logger::Loggable, + public: + explicit TraceSegmentReporter(Grpc::AsyncClientFactoryPtr&& factory, + Event::Dispatcher& dispatcher, Random::RandomGenerator& random, +- SkyWalkingTracerStats& stats, uint32_t delayed_buffer_size, ++ SkyWalkingTracerStatsSharedPtr stats, uint32_t delayed_buffer_size, + const std::string& token); + ~TraceSegmentReporter() override; + +@@ -46,7 +46,7 @@ private: + void handleFailure(); + void setRetryTimer(); + +- SkyWalkingTracerStats& tracing_stats_; ++ SkyWalkingTracerStatsSharedPtr tracing_stats_; + Grpc::AsyncClient client_; + Grpc::AsyncStream stream_{}; + const Protobuf::MethodDescriptor& service_method_; +diff --git a/source/extensions/upstreams/http/tcp/upstream_request.cc b/source/extensions/upstreams/http/tcp/upstream_request.cc +index 914e346d19..8af638ba16 100644 +--- a/source/extensions/upstreams/http/tcp/upstream_request.cc ++++ b/source/extensions/upstreams/http/tcp/upstream_request.cc +@@ -47,16 +47,19 @@ Envoy::Http::Status TcpUpstream::encodeHeaders(const Envoy::Http::RequestHeaderM + bool end_stream) { + // Headers should only happen once, so use this opportunity to add the proxy + // proto header, if configured. +- ASSERT(upstream_request_->routeEntry().connectConfig().has_value()); +- Buffer::OwnedImpl data; +- auto& connect_config = upstream_request_->routeEntry().connectConfig().value(); +- if (connect_config.has_proxy_protocol_config()) { +- Extensions::Common::ProxyProtocol::generateProxyProtoHeader( +- connect_config.proxy_protocol_config(), upstream_request_->connection(), data); +- } +- +- if (data.length() != 0 || end_stream) { +- upstream_conn_data_->connection().write(data, end_stream); ++ const Router::RouteEntry* route_entry = upstream_request_->route().routeEntry(); ++ ASSERT(route_entry != nullptr); ++ if (route_entry->connectConfig().has_value()) { ++ Buffer::OwnedImpl data; ++ auto& connect_config = route_entry->connectConfig().value(); ++ if (connect_config.has_proxy_protocol_config()) { ++ Extensions::Common::ProxyProtocol::generateProxyProtoHeader( ++ connect_config.proxy_protocol_config(), upstream_request_->connection(), data); ++ } ++ ++ if (data.length() != 0 || end_stream) { ++ upstream_conn_data_->connection().write(data, end_stream); ++ } + } + + // TcpUpstream::encodeHeaders is called after the UpstreamRequest is fully initialized. Also use +diff --git a/source/server/BUILD b/source/server/BUILD +index 3f4ed5f359..12de035da3 100644 +--- a/source/server/BUILD ++++ b/source/server/BUILD +@@ -150,6 +150,7 @@ envoy_cc_library( + "//envoy/network:listener_interface", + "//envoy/server:listener_manager_interface", + "//source/server:connection_handler_impl", ++ + ], + ) + +diff --git a/source/server/admin/BUILD b/source/server/admin/BUILD +index 365a5b8109..c0c22d55e3 100644 +--- a/source/server/admin/BUILD ++++ b/source/server/admin/BUILD +@@ -12,6 +12,9 @@ envoy_cc_library( + name = "admin_lib", + srcs = ["admin.cc"], + hdrs = ["admin.h"], ++ alimesh_deps = [ ++ "//contrib/server/admin/source:cluster_endpoints_handler_lib", ++ ], + deps = [ + ":admin_filter_lib", + ":clusters_handler_lib", +diff --git a/source/server/admin/admin.cc b/source/server/admin/admin.cc +index 74c17040b2..e9979ad537 100644 +--- a/source/server/admin/admin.cc ++++ b/source/server/admin/admin.cc +@@ -158,70 +158,73 @@ AdminImpl::AdminImpl(const std::string& profile_path, Server::Instance& server) + config_dump_handler_(config_tracker_, server), init_dump_handler_(server), + stats_handler_(server), logs_handler_(server), profiling_handler_(profile_path), + runtime_handler_(server), listeners_handler_(server), server_cmd_handler_(server), +- server_info_handler_(server), ++ server_info_handler_(server), cluster_endpoints_handler_(server), + // TODO(jsedgwick) add /runtime_reset endpoint that removes all admin-set values +- handlers_{ +- {"/", "Admin home page", MAKE_ADMIN_HANDLER(handlerAdminHome), false, false}, +- {"/certs", "print certs on machine", +- MAKE_ADMIN_HANDLER(server_info_handler_.handlerCerts), false, false}, +- {"/clusters", "upstream cluster status", +- MAKE_ADMIN_HANDLER(clusters_handler_.handlerClusters), false, false}, +- {"/config_dump", "dump current Envoy configs (experimental)", +- MAKE_ADMIN_HANDLER(config_dump_handler_.handlerConfigDump), false, false}, +- {"/init_dump", "dump current Envoy init manager information (experimental)", +- MAKE_ADMIN_HANDLER(init_dump_handler_.handlerInitDump), false, false}, +- {"/contention", "dump current Envoy mutex contention stats (if enabled)", +- MAKE_ADMIN_HANDLER(stats_handler_.handlerContention), false, false}, +- {"/cpuprofiler", "enable/disable the CPU profiler", +- MAKE_ADMIN_HANDLER(profiling_handler_.handlerCpuProfiler), false, true}, +- {"/heapprofiler", "enable/disable the heap profiler", +- MAKE_ADMIN_HANDLER(profiling_handler_.handlerHeapProfiler), false, true}, +- {"/healthcheck/fail", "cause the server to fail health checks", +- MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerHealthcheckFail), false, true}, +- {"/healthcheck/ok", "cause the server to pass health checks", +- MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerHealthcheckOk), false, true}, +- {"/help", "print out list of admin commands", MAKE_ADMIN_HANDLER(handlerHelp), false, +- false}, +- {"/hot_restart_version", "print the hot restart compatibility version", +- MAKE_ADMIN_HANDLER(server_info_handler_.handlerHotRestartVersion), false, false}, +- {"/logging", "query/change logging levels", +- MAKE_ADMIN_HANDLER(logs_handler_.handlerLogging), false, true}, +- {"/memory", "print current allocation/heap usage", +- MAKE_ADMIN_HANDLER(server_info_handler_.handlerMemory), false, false}, +- {"/quitquitquit", "exit the server", +- MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerQuitQuitQuit), false, true}, +- {"/reset_counters", "reset all counters to zero", +- MAKE_ADMIN_HANDLER(stats_handler_.handlerResetCounters), false, true}, +- {"/drain_listeners", "drain listeners", +- MAKE_ADMIN_HANDLER(listeners_handler_.handlerDrainListeners), false, true}, +- {"/server_info", "print server version/status information", +- MAKE_ADMIN_HANDLER(server_info_handler_.handlerServerInfo), false, false}, +- {"/ready", "print server state, return 200 if LIVE, otherwise return 503", +- MAKE_ADMIN_HANDLER(server_info_handler_.handlerReady), false, false}, +- {"/stats", "print server stats", MAKE_ADMIN_HANDLER(stats_handler_.handlerStats), false, +- false}, +- {"/stats/prometheus", "print server stats in prometheus format", +- MAKE_ADMIN_HANDLER(stats_handler_.handlerPrometheusStats), false, false}, +- {"/stats/recentlookups", "Show recent stat-name lookups", +- MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookups), false, false}, +- {"/stats/recentlookups/clear", "clear list of stat-name lookups and counter", +- MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookupsClear), false, true}, +- {"/stats/recentlookups/disable", "disable recording of reset stat-name lookup names", +- MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookupsDisable), false, true}, +- {"/stats/recentlookups/enable", "enable recording of reset stat-name lookup names", +- MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookupsEnable), false, true}, +- {"/listeners", "print listener info", +- MAKE_ADMIN_HANDLER(listeners_handler_.handlerListenerInfo), false, false}, +- {"/runtime", "print runtime values", MAKE_ADMIN_HANDLER(runtime_handler_.handlerRuntime), +- false, false}, +- {"/runtime_modify", "modify runtime values", +- MAKE_ADMIN_HANDLER(runtime_handler_.handlerRuntimeModify), false, true}, +- {"/reopen_logs", "reopen access logs", +- MAKE_ADMIN_HANDLER(logs_handler_.handlerReopenLogs), false, true}, +- }, +- date_provider_(server.dispatcher().timeSource()), +- admin_filter_chain_(std::make_shared()), +- local_reply_(LocalReply::Factory::createDefault()) {} ++ handlers_ { ++ {"/", "Admin home page", MAKE_ADMIN_HANDLER(handlerAdminHome), false, false}, ++ {"/certs", "print certs on machine", MAKE_ADMIN_HANDLER(server_info_handler_.handlerCerts), ++ false, false}, ++ {"/clusters", "upstream cluster status", ++ MAKE_ADMIN_HANDLER(clusters_handler_.handlerClusters), false, false}, ++ {"/config_dump", "dump current Envoy configs (experimental)", ++ MAKE_ADMIN_HANDLER(config_dump_handler_.handlerConfigDump), false, false}, ++ {"/init_dump", "dump current Envoy init manager information (experimental)", ++ MAKE_ADMIN_HANDLER(init_dump_handler_.handlerInitDump), false, false}, ++ {"/contention", "dump current Envoy mutex contention stats (if enabled)", ++ MAKE_ADMIN_HANDLER(stats_handler_.handlerContention), false, false}, ++ {"/cpuprofiler", "enable/disable the CPU profiler", ++ MAKE_ADMIN_HANDLER(profiling_handler_.handlerCpuProfiler), false, true}, ++ {"/heapprofiler", "enable/disable the heap profiler", ++ MAKE_ADMIN_HANDLER(profiling_handler_.handlerHeapProfiler), false, true}, ++ {"/healthcheck/fail", "cause the server to fail health checks", ++ MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerHealthcheckFail), false, true}, ++ {"/healthcheck/ok", "cause the server to pass health checks", ++ MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerHealthcheckOk), false, true}, ++ {"/help", "print out list of admin commands", MAKE_ADMIN_HANDLER(handlerHelp), false, false}, ++ {"/hot_restart_version", "print the hot restart compatibility version", ++ MAKE_ADMIN_HANDLER(server_info_handler_.handlerHotRestartVersion), false, false}, ++ {"/logging", "query/change logging levels", MAKE_ADMIN_HANDLER(logs_handler_.handlerLogging), ++ false, true}, ++ {"/memory", "print current allocation/heap usage", ++ MAKE_ADMIN_HANDLER(server_info_handler_.handlerMemory), false, false}, ++ {"/quitquitquit", "exit the server", ++ MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerQuitQuitQuit), false, true}, ++ {"/reset_counters", "reset all counters to zero", ++ MAKE_ADMIN_HANDLER(stats_handler_.handlerResetCounters), false, true}, ++ {"/drain_listeners", "drain listeners", ++ MAKE_ADMIN_HANDLER(listeners_handler_.handlerDrainListeners), false, true}, ++ {"/server_info", "print server version/status information", ++ MAKE_ADMIN_HANDLER(server_info_handler_.handlerServerInfo), false, false}, ++ {"/ready", "print server state, return 200 if LIVE, otherwise return 503", ++ MAKE_ADMIN_HANDLER(server_info_handler_.handlerReady), false, false}, ++ {"/stats", "print server stats", MAKE_ADMIN_HANDLER(stats_handler_.handlerStats), false, ++ false}, ++ {"/stats/prometheus", "print server stats in prometheus format", ++ MAKE_ADMIN_HANDLER(stats_handler_.handlerPrometheusStats), false, false}, ++ {"/stats/recentlookups", "Show recent stat-name lookups", ++ MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookups), false, false}, ++ {"/stats/recentlookups/clear", "clear list of stat-name lookups and counter", ++ MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookupsClear), false, true}, ++ {"/stats/recentlookups/disable", "disable recording of reset stat-name lookup names", ++ MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookupsDisable), false, true}, ++ {"/stats/recentlookups/enable", "enable recording of reset stat-name lookup names", ++ MAKE_ADMIN_HANDLER(stats_handler_.handlerStatsRecentLookupsEnable), false, true}, ++ {"/listeners", "print listener info", ++ MAKE_ADMIN_HANDLER(listeners_handler_.handlerListenerInfo), false, false}, ++ {"/runtime", "print runtime values", MAKE_ADMIN_HANDLER(runtime_handler_.handlerRuntime), ++ false, false}, ++ {"/runtime_modify", "modify runtime values", ++ MAKE_ADMIN_HANDLER(runtime_handler_.handlerRuntimeModify), false, true}, ++ {"/reopen_logs", "reopen access logs", MAKE_ADMIN_HANDLER(logs_handler_.handlerReopenLogs), ++ false, true}, ++#if defined(ALIMESH) ++ {"/endpoints", "print endpoints info related the service", ++ MAKE_ADMIN_HANDLER(cluster_endpoints_handler_.handlerClusterEndpoints), false, false}, ++#endif ++} ++, date_provider_(server.dispatcher().timeSource()), ++ admin_filter_chain_(std::make_shared()), ++ local_reply_(LocalReply::Factory::createDefault()) {} + + Http::ServerConnectionPtr AdminImpl::createCodec(Network::Connection& connection, + const Buffer::Instance& data, +diff --git a/source/server/admin/admin.h b/source/server/admin/admin.h +index e99330c2c8..2a7c81971a 100644 +--- a/source/server/admin/admin.h ++++ b/source/server/admin/admin.h +@@ -51,6 +51,10 @@ + + #include "absl/strings/string_view.h" + ++#if defined(ALIMESH) ++#include "contrib/server/admin/source/cluster_endpoints_handler.h" ++#endif ++ + namespace Envoy { + namespace Server { + +@@ -432,6 +436,9 @@ private: + Server::ListenersHandler listeners_handler_; + Server::ServerCmdHandler server_cmd_handler_; + Server::ServerInfoHandler server_info_handler_; ++#if defined(ALIMESH) ++ Server::ClusterEndpointsHandler cluster_endpoints_handler_; ++#endif + std::list handlers_; + const uint32_t max_request_headers_kb_{Http::DEFAULT_MAX_REQUEST_HEADERS_KB}; + const uint32_t max_request_headers_count_{Http::DEFAULT_MAX_HEADERS_COUNT}; +diff --git a/test/common/common/BUILD b/test/common/common/BUILD +index a4705d1bc4..f42d2b40f0 100644 +--- a/test/common/common/BUILD ++++ b/test/common/common/BUILD +@@ -182,10 +182,10 @@ envoy_cc_benchmark_binary( + deps = ["//source/common/common:minimal_logger_lib"], + ) + +-envoy_benchmark_test( +- name = "logger_speed_test_benchmark_test", +- benchmark_binary = "logger_speed_test", +-) ++# envoy_benchmark_test( ++# name = "logger_speed_test_benchmark_test", ++# benchmark_binary = "logger_speed_test", ++# ) + + envoy_cc_test( + name = "logger_test", +diff --git a/test/common/common/base64_test.cc b/test/common/common/base64_test.cc +index e00ae7f998..3c6bf92a05 100644 +--- a/test/common/common/base64_test.cc ++++ b/test/common/common/base64_test.cc +@@ -132,47 +132,6 @@ TEST(Base64Test, BinaryBufferEncode) { + EXPECT_EQ("AAECAwgKCQCqvN4=", Base64::encode(buffer, 30)); + } + +-TEST(Base64Test, CompletePadding) { +- struct CompletePaddingBase64UrlTestCases { +- std::string base64, base64_with_padding; +- }; +- +- // For base64 encoding, there are only three length needed to test +- // - 3n bytes => 4n bytes, no padding needed +- // - 3n + 1 bytes => 4n + 2 bytes, 2 padding needed +- // - 3n + 2 bytes => 4n + 3 bytes, 1 padding needed +- CompletePaddingBase64UrlTestCases testCases[3] = { +- // Payload text(3n bytes): +- {"eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG8iLCJpYXQiOjE1MTYyMzkwMjJ" +- "9", +- // No padding added. +- "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG8iLCJpYXQiOjE1MTYyMzkwMjJ" +- "9"}, +- // Payload text(3n + 1 bytes): +- {"eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2" +- "MjM5MDIyfQ", +- // 2 padding added. +- "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2" +- "MjM5MDIyfQ=="}, +- // Payload text(3n + 2 bytes): +- {"eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lZSIsImlhdCI6MTUx" +- "NjIzOTAyMn0", +- // 1 padding added. +- "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lZSIsImlhdCI6MTUx" +- "NjIzOTAyMn0="}}; +- for (auto& tc : testCases) { +- // Ensure these two base64 binaries are equivalent after decoding. +- EXPECT_EQ(Base64::decodeWithoutPadding(tc.base64), +- Base64::decodeWithoutPadding(tc.base64_with_padding)); +- // Ensure the `base64_with_padding` is correctly padded. +- EXPECT_NE(Base64::decode(tc.base64_with_padding), ""); +- +- std::string base64_padded = tc.base64; +- Base64::completePadding(base64_padded); +- EXPECT_EQ(base64_padded, tc.base64_with_padding); +- } +-} +- + TEST(Base64UrlTest, EncodeString) { + EXPECT_EQ("", Base64Url::encode("", 0)); + EXPECT_EQ("AAA", Base64Url::encode("\0\0", 2)); +diff --git a/test/common/filter/config_discovery_impl_test.cc b/test/common/filter/config_discovery_impl_test.cc +index ede45f2577..50d285fc09 100644 +--- a/test/common/filter/config_discovery_impl_test.cc ++++ b/test/common/filter/config_discovery_impl_test.cc +@@ -40,9 +40,11 @@ class FilterConfigDiscoveryTestBase : public testing::Test { + public: + FilterConfigDiscoveryTestBase() { + // For server_factory_context +- ON_CALL(factory_context_, scope()).WillByDefault(ReturnRef(scope_)); ++ ON_CALL(factory_context_.server_factory_context_, scope()).WillByDefault(ReturnRef(scope_)); + ON_CALL(factory_context_, messageValidationContext()) + .WillByDefault(ReturnRef(validation_context_)); ++ ON_CALL(factory_context_.server_factory_context_, messageValidationContext()) ++ .WillByDefault(ReturnRef(validation_context_)); + EXPECT_CALL(validation_context_, dynamicValidationVisitor()) + .WillRepeatedly(ReturnRef(validation_visitor_)); + EXPECT_CALL(factory_context_, initManager()).WillRepeatedly(ReturnRef(init_manager_)); +@@ -76,9 +78,9 @@ public: + } + ~FilterConfigDiscoveryImplTest() override { factory_context_.thread_local_.shutdownThread(); } + +- DynamicFilterConfigProviderPtr createProvider(std::string name, bool warm, +- bool default_configuration, +- bool last_filter_config = true) { ++ DynamicFilterConfigProviderPtr ++ createProvider(std::string name, bool warm, bool default_configuration, ++ bool last_filter_config = true) { + + EXPECT_CALL(init_manager_, add(_)); + envoy::config::core::v3::ExtensionConfigSource config_source; +@@ -113,16 +115,20 @@ type_urls: + + void setup(bool warm = true, bool default_configuration = false, bool last_filter_config = true) { + provider_ = createProvider("foo", warm, default_configuration, last_filter_config); +- callbacks_ = factory_context_.cluster_manager_.subscription_factory_.callbacks_; +- EXPECT_CALL(*factory_context_.cluster_manager_.subscription_factory_.subscription_, start(_)); ++ callbacks_ = ++ factory_context_.server_factory_context_.cluster_manager_.subscription_factory_.callbacks_; ++ EXPECT_CALL(*factory_context_.server_factory_context_.cluster_manager_.subscription_factory_ ++ .subscription_, ++ start(_)); + if (!warm) { + EXPECT_CALL(init_watcher_, ready()); + } + init_manager_.initialize(init_watcher_); + } + +- std::unique_ptr filter_config_provider_manager_; +- DynamicFilterConfigProviderPtr provider_; ++ std::unique_ptr> ++ filter_config_provider_manager_; ++ DynamicFilterConfigProviderPtr provider_; + Config::SubscriptionCallbacks* callbacks_{}; + }; + +diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc +index 6ca626f78d..cfae376d3a 100644 +--- a/test/common/formatter/substitution_formatter_test.cc ++++ b/test/common/formatter/substitution_formatter_test.cc +@@ -694,6 +694,24 @@ TEST(SubstitutionFormatterTest, streamInfoFormatter) { + } + + { ++ NiceMock stream_info; ++ StreamInfoFormatter upstream_format("VIRTUAL_CLUSTER_NAME"); ++ std::string virtual_cluster_name = "authN"; ++ stream_info.setVirtualClusterName(virtual_cluster_name); ++ EXPECT_EQ("authN", upstream_format.format(request_headers, response_headers, response_trailers, ++ stream_info, body)); ++ } ++ ++ { ++ NiceMock stream_info; ++ StreamInfoFormatter upstream_format("VIRTUAL_CLUSTER_NAME"); ++ EXPECT_EQ(absl::nullopt, upstream_format.format(request_headers, response_headers, ++ response_trailers, stream_info, body)); ++ } ++ ++ { ++ // Use a local stream info for these tests as as setSslConnection can only be called once. ++ NiceMock stream_info; + StreamInfoFormatter upstream_format("DOWNSTREAM_PEER_URI_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san"}; +diff --git a/test/common/grpc/grpc_client_integration.h b/test/common/grpc/grpc_client_integration.h +index 00aebe7cef..e0edd120ed 100644 +--- a/test/common/grpc/grpc_client_integration.h ++++ b/test/common/grpc/grpc_client_integration.h +@@ -13,7 +13,7 @@ namespace Envoy { + namespace Grpc { + + // Support parameterizing over state-of-the-world xDS vs delta xDS. +-enum class SotwOrDelta { Sotw, Delta }; ++enum class SotwOrDelta { Sotw, Delta, UnifiedSotw, UnifiedDelta }; + + class BaseGrpcClientIntegrationParamTest { + public: +diff --git a/test/common/http/codes_speed_test.cc b/test/common/http/codes_speed_test.cc +index fc1d5f4ffa..b79addb45e 100644 +--- a/test/common/http/codes_speed_test.cc ++++ b/test/common/http/codes_speed_test.cc +@@ -29,11 +29,20 @@ public: + void addResponse(uint64_t code, bool canary, bool internal_request, + Stats::StatName request_vhost_name = Stats::StatName(), + Stats::StatName request_vcluster_name = Stats::StatName(), ++ Stats::StatName request_route_name = Stats::StatName(), + Stats::StatName from_az = Stats::StatName(), + Stats::StatName to_az = Stats::StatName()) { +- Http::CodeStats::ResponseStatInfo info{ +- global_store_, cluster_scope_, prefix_, code, internal_request, +- request_vhost_name, request_vcluster_name, from_az, to_az, canary}; ++ Http::CodeStats::ResponseStatInfo info{global_store_, ++ cluster_scope_, ++ prefix_, ++ code, ++ internal_request, ++ request_vhost_name, ++ request_route_name, ++ request_vcluster_name, ++ from_az, ++ to_az, ++ canary}; + + code_stats_.chargeResponseStat(info, false); + } +@@ -52,10 +61,11 @@ public: + } + + void responseTiming() { ++ Stats::StatName empty_stat_name; + Http::CodeStats::ResponseTimingInfo info{ +- global_store_, cluster_scope_, prefix_, std::chrono::milliseconds(5), +- true, true, vhost_name_, req_vcluster_name_, +- from_az_, to_az_}; ++ global_store_, cluster_scope_, prefix_, std::chrono::milliseconds(5), true, ++ true, vhost_name_, empty_stat_name, req_vcluster_name_, from_az_, ++ to_az_}; + code_stats_.chargeResponseTiming(info); + } + +diff --git a/test/common/http/codes_test.cc b/test/common/http/codes_test.cc +index 98f80b7483..ab65280aa5 100644 +--- a/test/common/http/codes_test.cc ++++ b/test/common/http/codes_test.cc +@@ -37,9 +37,11 @@ public: + Stats::StatName to_zone = pool_.add(to_az); + Stats::StatName vhost_name = pool_.add(request_vhost_name); + Stats::StatName vcluster_name = pool_.add(request_vcluster_name); ++ Stats::StatName empty_stat_name; + Http::CodeStats::ResponseStatInfo info{ +- global_store_, cluster_scope_, prefix, code, internal_request, +- vhost_name, vcluster_name, from_zone, to_zone, canary}; ++ global_store_, cluster_scope_, prefix, code, ++ internal_request, vhost_name, vcluster_name, empty_stat_name, ++ from_zone, to_zone, canary}; + + code_stats_.chargeResponseStat(info, false); + } +@@ -232,6 +234,7 @@ TEST_F(CodeUtilityTest, PerZoneStats) { + TEST_F(CodeUtilityTest, ResponseTimingTest) { + Stats::MockStore global_store; + Stats::MockStore cluster_scope; ++ Stats::StatName empty_stat_name; + + Stats::StatNameManagedStorage prefix("prefix", *symbol_table_); + Http::CodeStats::ResponseTimingInfo info{global_store, +@@ -242,6 +245,7 @@ TEST_F(CodeUtilityTest, ResponseTimingTest) { + true, + pool_.add("vhost_name"), + pool_.add("req_vcluster_name"), ++ empty_stat_name, + pool_.add("from_az"), + pool_.add("to_az")}; + +diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc +index 05a3a0d59d..9d2a11d6f2 100644 +--- a/test/common/http/conn_manager_impl_test.cc ++++ b/test/common/http/conn_manager_impl_test.cc +@@ -2162,7 +2162,8 @@ TEST_F(HttpConnectionManagerImplTest, TestAccessLogWithInvalidRequest) { + + class StreamErrorOnInvalidHttpMessageTest : public HttpConnectionManagerImplTest { + public: +- void sendInvalidRequestAndVerifyConnectionState(bool stream_error_on_invalid_http_message) { ++ void sendInvalidRequestAndVerifyConnectionState(bool stream_error_on_invalid_http_message, ++ bool send_complete_request = true) { + setup(false, ""); + + EXPECT_CALL(*codec_, dispatch(_)) +@@ -2172,7 +2173,7 @@ public: + // These request headers are missing the necessary ":host" + RequestHeaderMapPtr headers{ + new TestRequestHeaderMapImpl{{":method", "GET"}, {":path", "/"}}}; +- decoder_->decodeHeaders(std::move(headers), true); ++ decoder_->decodeHeaders(std::move(headers), send_complete_request); + data.drain(0); + return Http::okStatus(); + })); +@@ -2190,6 +2191,19 @@ public: + .WillOnce(Return(stream_error_on_invalid_http_message)); + EXPECT_CALL(*filter, encodeComplete()); + EXPECT_CALL(*filter, encodeHeaders(_, true)); ++ if (!stream_error_on_invalid_http_message) { ++ EXPECT_CALL(filter_callbacks_.connection_, close(_)).Times(AnyNumber()); ++ if (send_complete_request) { ++ // The request is complete, so we should not flush close. ++ EXPECT_CALL(filter_callbacks_.connection_, close(Network::ConnectionCloseType::FlushWrite)) ++ .Times(AnyNumber()); ++ } else { ++ // If the request isn't complete, avoid a FIN/RST race with delay close. ++ EXPECT_CALL(filter_callbacks_.connection_, ++ close(Network::ConnectionCloseType::FlushWriteAndDelay)) ++ .Times(AnyNumber()); ++ } ++ } + EXPECT_CALL(response_encoder_, encodeHeaders(_, true)) + .WillOnce(Invoke([&](const ResponseHeaderMap& headers, bool) -> void { + EXPECT_EQ("400", headers.getStatusValue()); +@@ -2215,6 +2229,12 @@ TEST_F(StreamErrorOnInvalidHttpMessageTest, ConnectionTerminatedIfCodecStreamErr + sendInvalidRequestAndVerifyConnectionState(false); + } + ++TEST_F(StreamErrorOnInvalidHttpMessageTest, ++ ConnectionTerminatedWithDelayIfCodecStreamErrorIsFalse) { ++ // Same as above, only with an incomplete request. ++ sendInvalidRequestAndVerifyConnectionState(false, false); ++} ++ + TEST_F(StreamErrorOnInvalidHttpMessageTest, ConnectionOpenIfCodecStreamErrorIsTrue) { + sendInvalidRequestAndVerifyConnectionState(true); + } +@@ -3365,7 +3385,7 @@ TEST_F(HttpConnectionManagerImplTest, Http10Rejected) { + decoder_ = &conn_manager_->newStream(response_encoder_); + RequestHeaderMapPtr headers{ + new TestRequestHeaderMapImpl{{":authority", "host"}, {":method", "GET"}, {":path", "/"}}}; +- decoder_->decodeHeaders(std::move(headers), true); ++ decoder_->decodeHeaders(std::move(headers), false); + data.drain(4); + return Http::okStatus(); + })); +@@ -3375,6 +3395,12 @@ TEST_F(HttpConnectionManagerImplTest, Http10Rejected) { + EXPECT_EQ("426", headers.getStatusValue()); + EXPECT_EQ("close", headers.getConnectionValue()); + })); ++ // No delay close for HTTP/1.0, even if the request is not complete. ++ // Note there may be more than one close: the important thing is one does not ++ // kick off delay. ++ EXPECT_CALL(filter_callbacks_.connection_, close(_)).Times(AnyNumber()); ++ EXPECT_CALL(filter_callbacks_.connection_, close(Network::ConnectionCloseType::FlushWrite)) ++ .Times(AnyNumber()); + + Buffer::OwnedImpl fake_input("1234"); + conn_manager_->onData(fake_input, false); +diff --git a/test/common/http/header_map_impl_test.cc b/test/common/http/header_map_impl_test.cc +index ce4bb8a7cc..d06806f23a 100644 +--- a/test/common/http/header_map_impl_test.cc ++++ b/test/common/http/header_map_impl_test.cc +@@ -423,9 +423,8 @@ TEST_P(HeaderMapImplTest, AllInlineHeaders) { + INLINE_REQ_RESP_STRING_HEADERS(TEST_INLINE_STRING_HEADER_FUNCS) + } + { +- // No request trailer O(1) headers. +- } +- { ++ // No request trailer O(1) headers. ++ } { + auto header_map = ResponseHeaderMapImpl::create(); + INLINE_RESP_STRING_HEADERS(TEST_INLINE_STRING_HEADER_FUNCS) + INLINE_REQ_RESP_STRING_HEADERS(TEST_INLINE_STRING_HEADER_FUNCS) +@@ -796,6 +795,88 @@ TEST_P(HeaderMapImplTest, SetReferenceKey) { + EXPECT_EQ("monde", headers.get(foo)[0]->value().getStringView()); + } + ++ ++#if defined(ALIMESH) ++TEST_P(HeaderMapImplTest, OriginalHost) { ++ // Normal case. ++ { ++ TestRequestHeaderMapImpl headers; ++ headers.setHost("blah"); ++ headers.setReferenceKey(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost, ++ headers.getHostValue()); ++ EXPECT_EQ("blah", headers.getHostValue()); ++ ++ headers.setHost("example"); ++ EXPECT_EQ("example", headers.getHostValue()); ++ ++ const auto original_host = ++ headers.getByKey(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost); ++ EXPECT_EQ("blah", original_host.value()); ++ } ++ ++ // Normal case. ++ { ++ TestRequestHeaderMapImpl headers; ++ headers.setHost("www.example.com"); ++ headers.setReferenceKey(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost, ++ headers.getHostValue()); ++ EXPECT_EQ("www.example.com", headers.getHostValue()); ++ ++ headers.setHost("test.com"); ++ EXPECT_EQ("test.com", headers.getHostValue()); ++ ++ const auto original_host = ++ headers.getByKey(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost); ++ EXPECT_EQ("www.example.com", original_host.value()); ++ } ++ ++ // The header 'EnvoyOriginalHost' value is overwritten. ++ { ++ TestRequestHeaderMapImpl headers; ++ headers.setHost("blah"); ++ headers.setReference(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost, ++ headers.getHostValue()); ++ EXPECT_EQ("blah", headers.getHostValue()); ++ ++ headers.setHost("example"); ++ EXPECT_EQ("example", headers.getHostValue()); ++ ++ const auto original_host = ++ headers.getByKey(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost); ++ EXPECT_EQ("exam", original_host.value()); ++ } ++ ++ // The header 'EnvoyOriginalHost' value is overwritten. ++ { ++ TestRequestHeaderMapImpl headers; ++ headers.setHost("www.example.com"); ++ headers.setReference(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost, ++ headers.getHostValue()); ++ EXPECT_EQ("www.example.com", headers.getHostValue()); ++ ++ headers.setHost("test.com"); ++ EXPECT_EQ("test.com", headers.getHostValue()); ++ ++ const auto original_host = ++ headers.getByKey(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost); ++ EXPECT_NE("test.com", original_host.value()); ++ } ++} ++#endif ++ ++TEST_P(HeaderMapImplTest, SetReferenceKeyTest111) { ++ TestRequestHeaderMapImpl headers; ++ //headers.setReferenceKey(Headers::get().Host, "blah"); ++ headers.setHost("blah"); ++ EXPECT_EQ("blah", headers.getHostValue()); ++ ++ headers.setReference(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost, headers.getHostValue()); ++ // headers.setReferenceKey(Headers::get().Host, "blahxxx"); ++ headers.setHost("blahxxxx"); ++ EXPECT_EQ("blahxxxx", headers.getHostValue()); ++ EXPECT_EQ("blah", headers.get(Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost)[0]->value().getStringView()); ++} ++ + TEST_P(HeaderMapImplTest, SetCopy) { + TestRequestHeaderMapImpl headers; + LowerCaseString foo("hello"); +diff --git a/test/common/http/utility_test.cc b/test/common/http/utility_test.cc +index ae7073574d..5509c5ff3f 100644 +--- a/test/common/http/utility_test.cc ++++ b/test/common/http/utility_test.cc +@@ -301,6 +301,92 @@ TEST(HttpUtility, appendVia) { + } + } + ++TEST(HttpUtility, updateAuthority) { ++ { ++ TestRequestHeaderMapImpl headers; ++ Utility::updateAuthority(headers, "dns.name", true); ++ EXPECT_EQ("dns.name", headers.get_(":authority")); ++ EXPECT_EQ("", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers; ++ Utility::updateAuthority(headers, "dns.name", false); ++ EXPECT_EQ("dns.name", headers.get_(":authority")); ++ EXPECT_EQ("", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers; ++ Utility::updateAuthority(headers, "", true); ++ EXPECT_EQ("", headers.get_(":authority")); ++ EXPECT_EQ("", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers; ++ Utility::updateAuthority(headers, "", false); ++ EXPECT_EQ("", headers.get_(":authority")); ++ EXPECT_EQ("", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{":authority", "host.com"}}; ++ Utility::updateAuthority(headers, "dns.name", true); ++ EXPECT_EQ("dns.name", headers.get_(":authority")); ++ EXPECT_EQ("host.com", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{":authority", "host.com"}}; ++ Utility::updateAuthority(headers, "dns.name", false); ++ EXPECT_EQ("dns.name", headers.get_(":authority")); ++ EXPECT_EQ("", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{":authority", "host.com"}}; ++ Utility::updateAuthority(headers, "", true); ++ EXPECT_EQ("", headers.get_(":authority")); ++ EXPECT_EQ("host.com", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{":authority", "host.com"}}; ++ Utility::updateAuthority(headers, "", false); ++ EXPECT_EQ("", headers.get_(":authority")); ++ EXPECT_EQ("", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{":authority", "dns.name"}, {"x-forwarded-host", "host.com"}}; ++ Utility::updateAuthority(headers, "newhost.com", true); ++ EXPECT_EQ("newhost.com", headers.get_(":authority")); ++ EXPECT_EQ("host.com,dns.name", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{":authority", "dns.name"}, {"x-forwarded-host", "host.com"}}; ++ Utility::updateAuthority(headers, "newhost.com", false); ++ EXPECT_EQ("newhost.com", headers.get_(":authority")); ++ EXPECT_EQ("host.com", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{"x-forwarded-host", "host.com"}}; ++ Utility::updateAuthority(headers, "dns.name", true); ++ EXPECT_EQ("dns.name", headers.get_(":authority")); ++ EXPECT_EQ("host.com", headers.get_("x-forwarded-host")); ++ } ++ ++ { ++ TestRequestHeaderMapImpl headers{{"x-forwarded-host", "host.com"}}; ++ Utility::updateAuthority(headers, "dns.name", false); ++ EXPECT_EQ("dns.name", headers.get_(":authority")); ++ EXPECT_EQ("host.com", headers.get_("x-forwarded-host")); ++ } ++} ++ + TEST(HttpUtility, createSslRedirectPath) { + { + TestRequestHeaderMapImpl headers{{":authority", "www.lyft.com"}, {":path", "/hello"}}; +diff --git a/test/common/network/apple_dns_impl_test.cc b/test/common/network/apple_dns_impl_test.cc +index b7e7904ad7..df35c4063d 100644 +--- a/test/common/network/apple_dns_impl_test.cc ++++ b/test/common/network/apple_dns_impl_test.cc +@@ -916,7 +916,7 @@ TEST_F(AppleDnsImplFakeApiTest, ResultWithNullAddress) { + + auto query = resolver_->resolve( + hostname, Network::DnsLookupFamily::Auto, +- [](DnsResolver::ResolutionStatus, std::list&&) -> void { FAIL(); }); ++ [](DnsResolver::ResolutionStatus, std::list &&) -> void { FAIL(); }); + ASSERT_NE(nullptr, query); + + EXPECT_DEATH(reply_callback(nullptr, kDNSServiceFlagsAdd, 0, kDNSServiceErr_NoError, +diff --git a/test/common/network/cidr_range_test.cc b/test/common/network/cidr_range_test.cc +index 6232e910dd..f3abc89a1a 100644 +--- a/test/common/network/cidr_range_test.cc ++++ b/test/common/network/cidr_range_test.cc +@@ -12,6 +12,10 @@ + + #include "gtest/gtest.h" + ++#if defined(ALIMESH) ++#include "test/test_common/environment.h" ++#endif ++ + // We are adding things into the std namespace. + // Note that this is technically undefined behavior! + namespace std { +diff --git a/test/common/network/udp_listener_impl_batch_writer_test.cc b/test/common/network/udp_listener_impl_batch_writer_test.cc +index 39b69e86c0..414cc968b8 100644 +--- a/test/common/network/udp_listener_impl_batch_writer_test.cc ++++ b/test/common/network/udp_listener_impl_batch_writer_test.cc +@@ -92,6 +92,9 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, UdpListenerImplBatchWriterTest, + * total_bytes_sent counter is updated accordingly. + */ + TEST_P(UdpListenerImplBatchWriterTest, SendData) { ++ if (!TestEnvironment::shouldRunTestForIpVersion(Network::Address::IpVersion::v6)) { ++ return; ++ } + EXPECT_TRUE(udp_packet_writer_->isBatchMode()); + Address::InstanceConstSharedPtr send_from_addr = getNonDefaultSourceAddress(); + +@@ -177,6 +180,9 @@ TEST_P(UdpListenerImplBatchWriterTest, SendData) { + * Internal Buffer. + */ + TEST_P(UdpListenerImplBatchWriterTest, WriteBlocked) { ++ if (!TestEnvironment::shouldRunTestForIpVersion(Network::Address::IpVersion::v6)) { ++ return; ++ } + // Quic Mock Objects + quic::test::MockQuicSyscallWrapper os_sys_calls; + quic::ScopedGlobalSyscallWrapperOverride os_calls(&os_sys_calls); +diff --git a/test/common/network/udp_listener_impl_test.cc b/test/common/network/udp_listener_impl_test.cc +index a16a13e8f5..61a69a3f9a 100644 +--- a/test/common/network/udp_listener_impl_test.cc ++++ b/test/common/network/udp_listener_impl_test.cc +@@ -107,6 +107,9 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, UdpListenerImplTest, + * Tests UDP listener for actual destination and data. + */ + TEST_P(UdpListenerImplTest, UseActualDstUdp) { ++ if (!TestEnvironment::shouldRunTestForIpVersion(Network::Address::IpVersion::v6)) { ++ return; ++ } + setup(); + + // We send 2 packets +@@ -140,6 +143,9 @@ TEST_P(UdpListenerImplTest, UseActualDstUdp) { + + // Test a large datagram that gets dropped using recvmsg or recvmmsg if supported. + TEST_P(UdpListenerImplTest, LargeDatagramRecvmmsg) { ++ if (!TestEnvironment::shouldRunTestForIpVersion(Network::Address::IpVersion::v6)) { ++ return; ++ } + setup(); + + // This will get dropped. +diff --git a/test/common/network/utility_test.cc b/test/common/network/utility_test.cc +index fac1300cf3..b9892ead84 100644 +--- a/test/common/network/utility_test.cc ++++ b/test/common/network/utility_test.cc +@@ -353,6 +353,7 @@ TEST(NetworkUtility, LoopbackAddress) { + Address::PipeInstance address("/foo"); + EXPECT_FALSE(Utility::isLoopbackAddress(address)); + } ++ + { + Address::Ipv6Instance address("::1"); + EXPECT_TRUE(Utility::isLoopbackAddress(address)); +@@ -532,7 +533,11 @@ TEST(PortRangeListTest, Normal) { + + // TODO(ccaraman): Support big-endian. These tests operate under the assumption that the machine + // byte order is little-endian. ++#if defined(ALIMESH) ++TEST(AbslUint128, DISABLED_TestByteOrder) { ++#else + TEST(AbslUint128, TestByteOrder) { ++#endif + { + Address::Ipv6Instance address("::1"); + uint64_t high = 0x100000000000000; +diff --git a/test/common/router/BUILD b/test/common/router/BUILD +index 596a8a86e7..0d6ca09fe0 100644 +--- a/test/common/router/BUILD ++++ b/test/common/router/BUILD +@@ -33,6 +33,7 @@ envoy_cc_test_library( + "//source/common/stream_info:filter_state_lib", + "//test/extensions/filters/http/common:empty_http_filter_config_lib", + "//test/fuzz:utility_lib", ++ "//test/mocks/router:router_mocks", + "//test/mocks/server:instance_mocks", + "//test/mocks/upstream:retry_priority_mocks", + "//test/test_common:environment_lib", +@@ -44,6 +45,20 @@ envoy_cc_test_library( + ], + ) + ++envoy_cc_test( ++ name = "config_impl_integration_test", ++ srcs = [ ++ "config_impl_integration_test.cc", ++ ], ++ deps = [ ++ "//source/common/protobuf", ++ "//source/common/router:config_lib", ++ "//test/integration:http_integration_lib", ++ "//test/test_common:utility_lib", ++ "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto", ++ ], ++) ++ + envoy_cc_benchmark_binary( + name = "config_impl_headermap_benchmark_test", + srcs = ["config_impl_headermap_benchmark_test.cc"], +diff --git a/test/common/router/config_impl_integration_test.cc b/test/common/router/config_impl_integration_test.cc +new file mode 100644 +index 0000000000..db68766c85 +--- /dev/null ++++ b/test/common/router/config_impl_integration_test.cc +@@ -0,0 +1,144 @@ ++#include ++#include ++ ++#include "envoy/config/endpoint/v3/endpoint_components.pb.h" ++ ++#include "source/common/common/base64.h" ++#include "source/common/http/utility.h" ++#include "source/common/protobuf/protobuf.h" ++ ++#include "test/integration/http_integration.h" ++#include "test/test_common/registry.h" ++ ++#include "absl/strings/string_view.h" ++#include "gtest/gtest.h" ++ ++namespace Envoy { ++namespace Router { ++namespace { ++ ++class FakeClusterSpecifierPluginFactoryConfig : public ClusterSpecifierPluginFactoryConfig { ++public: ++ class FakeClusterSpecifierPlugin : public ClusterSpecifierPlugin { ++ public: ++ FakeClusterSpecifierPlugin(absl::string_view cluster) : cluster_name_(cluster) {} ++ ++ RouteConstSharedPtr route(const RouteEntry& parent, ++ const Http::RequestHeaderMap&) const override { ++ ASSERT(dynamic_cast(&parent) != nullptr); ++ return std::make_shared( ++ dynamic_cast(&parent), cluster_name_); ++ } ++ ++ const std::string cluster_name_; ++ }; ++ ++ FakeClusterSpecifierPluginFactoryConfig() = default; ++ ClusterSpecifierPluginSharedPtr ++ createClusterSpecifierPlugin(const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext&) override { ++ const auto& typed_config = dynamic_cast(config); ++ return std::make_shared( ++ typed_config.fields().at("name").string_value()); ++ } ++ ++ ProtobufTypes::MessagePtr createEmptyConfigProto() override { ++ return std::make_unique(); ++ } ++ ++ std::string name() const override { return "envoy.router.cluster_specifier_plugin.fake"; } ++}; ++ ++class ConfigImplIntegrationTest : public Envoy::HttpIntegrationTest, public testing::Test { ++public: ++ ConfigImplIntegrationTest() ++ : HttpIntegrationTest(Http::CodecType::HTTP1, Network::Address::IpVersion::v4) {} ++ ++ void initializeRoute(const std::string& vhost_config_yaml) { ++ envoy::config::route::v3::VirtualHost vhost; ++ TestUtility::loadFromYaml(vhost_config_yaml, vhost); ++ config_helper_.addVirtualHost(vhost); ++ initialize(); ++ } ++}; ++ ++static const std::string ClusterSpecifierPluginUnknownCluster = ++ R"EOF( ++name: test_cluster_specifier_plugin ++domains: ++- cluster.specifier.plugin ++routes: ++- name: test_route_1 ++ match: ++ prefix: /test/route/1 ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: fake ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ name: cluster_0 ++- name: test_route_2 ++ match: ++ prefix: /test/route/2 ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: fake ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ name: cluster_unknown ++)EOF"; ++ ++TEST_F(ConfigImplIntegrationTest, ClusterSpecifierPluginTest) { ++ FakeClusterSpecifierPluginFactoryConfig factory; ++ Registry::InjectFactory registered(factory); ++ ++ initializeRoute(ClusterSpecifierPluginUnknownCluster); ++ ++ { ++ codec_client_ = makeHttpConnection(lookupPort("http")); ++ ++ Http::TestResponseHeaderMapImpl response_headers{ ++ {"server", "envoy"}, ++ {":status", "200"}, ++ }; ++ ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/test/route/1"}, ++ {":scheme", "http"}, ++ {":authority", "cluster.specifier.plugin"}}; ++ ++ auto response = sendRequestAndWaitForResponse(request_headers, 0, response_headers, 0); ++ ++ ASSERT_TRUE(response->waitForEndStream()); ++ EXPECT_TRUE(response->complete()); ++ EXPECT_EQ(response->headers().getStatusValue(), "200"); ++ ++ cleanupUpstreamAndDownstream(); ++ } ++ ++ { ++ codec_client_ = makeHttpConnection(lookupPort("http")); ++ ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/test/route/2"}, ++ {":scheme", "http"}, ++ {":authority", "cluster.specifier.plugin"}}; ++ ++ // Second route will be selected and unknown cluster name will be return by the cluster ++ // specifier plugin. ++ auto response = codec_client_->makeHeaderOnlyRequest(request_headers); ++ ASSERT_TRUE(response->waitForEndStream()); ++ EXPECT_TRUE(response->complete()); ++ EXPECT_THAT(response->headers(), Http::HttpStatusIs("503")); ++ ++ cleanupUpstreamAndDownstream(); ++ } ++} ++ ++} // namespace ++} // namespace Router ++} // namespace Envoy +diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc +index c540db9e12..7652fc001c 100644 +--- a/test/common/router/config_impl_test.cc ++++ b/test/common/router/config_impl_test.cc +@@ -24,6 +24,7 @@ + #include "test/common/router/route_fuzz.pb.h" + #include "test/extensions/filters/http/common/empty_http_filter_config.h" + #include "test/fuzz/utility.h" ++#include "test/mocks/router/mocks.h" + #include "test/mocks/server/instance.h" + #include "test/mocks/upstream/retry_priority.h" + #include "test/mocks/upstream/retry_priority_factory.h" +@@ -648,11 +649,13 @@ virtual_hosts: + route: + cluster: ats + host_rewrite_header: x-rewrite-host ++ append_x_forwarded_host: true + - match: + path: "/do-not-rewrite-host-with-header-value" + route: + cluster: ats + host_rewrite_header: x-rewrite-host ++ append_x_forwarded_host: true + - match: + path: "/rewrite-host-with-path-regex/envoyproxy.io" + route: +@@ -662,6 +665,7 @@ virtual_hosts: + google_re2: {} + regex: "^/.+/(.+)$" + substitution: \1 ++ append_x_forwarded_host: true + - match: + prefix: "/" + route: +@@ -935,6 +939,9 @@ virtual_hosts: + EXPECT_FALSE(route->currentUrlPathAfterRewrite(headers).has_value()); + route->finalizeRequestHeaders(headers, stream_info, true); + EXPECT_EQ("new_host", headers.get_(Http::Headers::get().Host)); ++ // Config setting append_x_forwarded_host is false (by default). Expect empty x-forwarded-host ++ // header value. ++ EXPECT_EQ("", headers.get_(Http::Headers::get().ForwardedHost)); + } + + // Rewrites host using supplied header. +@@ -945,6 +952,7 @@ virtual_hosts: + EXPECT_FALSE(route->currentUrlPathAfterRewrite(headers).has_value()); + route->finalizeRequestHeaders(headers, stream_info, true); + EXPECT_EQ("rewrote", headers.get_(Http::Headers::get().Host)); ++ EXPECT_EQ("api.lyft.com", headers.get_(Http::Headers::get().ForwardedHost)); + } + + // Does not rewrite host because of missing header. +@@ -955,6 +963,7 @@ virtual_hosts: + EXPECT_FALSE(route->currentUrlPathAfterRewrite(headers).has_value()); + route->finalizeRequestHeaders(headers, stream_info, true); + EXPECT_EQ("api.lyft.com", headers.get_(Http::Headers::get().Host)); ++ EXPECT_EQ("", headers.get_(Http::Headers::get().ForwardedHost)); + } + + // Rewrites host using path. +@@ -965,6 +974,7 @@ virtual_hosts: + EXPECT_FALSE(route->currentUrlPathAfterRewrite(headers).has_value()); + route->finalizeRequestHeaders(headers, stream_info, true); + EXPECT_EQ("envoyproxy.io", headers.get_(Http::Headers::get().Host)); ++ EXPECT_EQ("api.lyft.com", headers.get_(Http::Headers::get().ForwardedHost)); + } + + // Rewrites host using path, removes query parameters +@@ -975,6 +985,7 @@ virtual_hosts: + EXPECT_FALSE(route->currentUrlPathAfterRewrite(headers).has_value()); + route->finalizeRequestHeaders(headers, stream_info, true); + EXPECT_EQ("envoyproxy.io", headers.get_(Http::Headers::get().Host)); ++ EXPECT_EQ("api.lyft.com", headers.get_(Http::Headers::get().ForwardedHost)); + } + + // Case sensitive rewrite matching test. +@@ -2924,6 +2935,419 @@ TEST_F(RouteMatcherTest, WeightedClusterHeader) { + EXPECT_EQ("cluster2", config.route(headers, 560)->routeEntry()->clusterName()); + } + ++TEST_F(RouteMatcherTest, InlineClusterSpecifierPlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: test ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock factory; ++ Registry::InjectFactory registered(factory); ++ ++ auto mock_cluster_specifier_plugin = std::make_shared>(); ++ ++ EXPECT_CALL(factory, createClusterSpecifierPlugin(_, _)) ++ .WillOnce(Return(mock_cluster_specifier_plugin)); ++ ++ NiceMock stream_info; ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ ++ auto mock_route = std::make_shared>(); ++ ++ EXPECT_CALL(*mock_cluster_specifier_plugin, route(_, _)).WillOnce(Return(mock_route)); ++ ++ EXPECT_EQ(mock_route.get(), config.route(genHeaders("some_cluster", "/foo", "GET"), 0).get()); ++} ++ ++TEST_F(RouteMatcherTest, UnknownClusterSpecifierPlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: test ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock stream_info; ++ EXPECT_THROW_WITH_REGEX( ++ TestConfigImpl(parseRouteConfigurationFromYaml(yaml), factory_context_, true), EnvoyException, ++ "Didn't find a registered implementation for.*"); ++} ++ ++TEST_F(RouteMatcherTest, UnknownClusterSpecifierPluginButOptional) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ inline_cluster_specifier_plugin: ++ extension: ++ name: test ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ is_optional: true ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_header: some_header ++ timeout: 0s ++ )EOF"; ++ ++ NiceMock stream_info; ++ EXPECT_NO_THROW(TestConfigImpl(parseRouteConfigurationFromYaml(yaml), factory_context_, true)); ++} ++ ++TEST_F(RouteMatcherTest, ClusterSpecifierPlugin) { ++ const std::string yaml = R"EOF( ++cluster_specifier_plugins: ++- extension: ++ name: test1 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test1 ++- extension: ++ name: test2 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test2 ++- extension: ++ name: test3 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test3 ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ cluster_specifier_plugin: test2 ++ - match: ++ prefix: "/bar" ++ route: ++ cluster_specifier_plugin: test3 ++ )EOF"; ++ ++ NiceMock factory; ++ Registry::InjectFactory registered(factory); ++ ++ auto mock_cluster_specifier_plugin_1 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_2 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_3 = std::make_shared>(); ++ ++ EXPECT_CALL(factory, createClusterSpecifierPlugin(_, _)) ++ .WillRepeatedly(Invoke( ++ [mock_cluster_specifier_plugin_1, mock_cluster_specifier_plugin_2, ++ mock_cluster_specifier_plugin_3]( ++ const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext&) -> ClusterSpecifierPluginSharedPtr { ++ const auto& typed_config = dynamic_cast(config); ++ if (auto iter = typed_config.fields().find("a"); iter == typed_config.fields().end()) { ++ return nullptr; ++ } else if (iter->second.string_value() == "test1") { ++ return mock_cluster_specifier_plugin_1; ++ } else if (iter->second.string_value() == "test2") { ++ return mock_cluster_specifier_plugin_2; ++ } else if (iter->second.string_value() == "test3") { ++ return mock_cluster_specifier_plugin_3; ++ } ++ return nullptr; ++ })); ++ ++ NiceMock stream_info; ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ ++ auto mock_route = std::make_shared>(); ++ ++ EXPECT_CALL(*mock_cluster_specifier_plugin_2, route(_, _)).WillOnce(Return(mock_route)); ++ EXPECT_EQ(mock_route.get(), config.route(genHeaders("some_cluster", "/foo", "GET"), 0).get()); ++ ++ EXPECT_CALL(*mock_cluster_specifier_plugin_3, route(_, _)).WillOnce(Return(mock_route)); ++ EXPECT_EQ(mock_route.get(), config.route(genHeaders("some_cluster", "/bar", "GET"), 0).get()); ++} ++ ++#if defined(ALIMESH) ++TEST_F(RouteMatcherTest, WeightedClusterSpecifierPlugin) { ++ const std::string yaml = R"EOF( ++cluster_specifier_plugins: ++- extension: ++ name: test1 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test1 ++- extension: ++ name: test2 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test2 ++- extension: ++ name: test3 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test3 ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: cluster1 ++ weight: 50 ++ - name: cluster2 ++ weight: 50 ++ total_weight: 100 ++ cluster_specifier_plugin: test2 ++ - match: ++ prefix: "/bar" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: cluster1 ++ weight: 50 ++ - name: cluster2 ++ weight: 50 ++ total_weight: 100 ++ cluster_specifier_plugin: test3 ++ )EOF"; ++ ++ NiceMock factory; ++ Registry::InjectFactory registered(factory); ++ ++ auto mock_cluster_specifier_plugin_1 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_2 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_3 = std::make_shared>(); ++ ++ factory_context_.cluster_manager_.initializeClusters({"cluster1", "cluster2"}, {}); ++ ++ EXPECT_CALL(factory, createClusterSpecifierPlugin(_, _)) ++ .WillRepeatedly(Invoke( ++ [mock_cluster_specifier_plugin_1, mock_cluster_specifier_plugin_2, ++ mock_cluster_specifier_plugin_3]( ++ const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext&) -> ClusterSpecifierPluginSharedPtr { ++ const auto& typed_config = dynamic_cast(config); ++ if (auto iter = typed_config.fields().find("a"); iter == typed_config.fields().end()) { ++ return nullptr; ++ } else if (iter->second.string_value() == "test1") { ++ return mock_cluster_specifier_plugin_1; ++ } else if (iter->second.string_value() == "test2") { ++ return mock_cluster_specifier_plugin_2; ++ } else if (iter->second.string_value() == "test3") { ++ return mock_cluster_specifier_plugin_3; ++ } ++ return nullptr; ++ })); ++ ++ NiceMock stream_info; ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ ++ auto mock_route = std::make_shared>(); ++ ++ EXPECT_CALL(*mock_cluster_specifier_plugin_2, route(_, _)).WillOnce(Return(mock_route)); ++ EXPECT_EQ(mock_route.get(), config.route(genHeaders("some_cluster", "/foo", "GET"), 0).get()); ++ ++ EXPECT_CALL(*mock_cluster_specifier_plugin_3, route(_, _)).WillOnce(Return(mock_route)); ++ EXPECT_EQ(mock_route.get(), config.route(genHeaders("some_cluster", "/bar", "GET"), 0).get()); ++} ++ ++TEST_F(RouteMatcherTest, WeightedClusterInlineSpecifierPlugin) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: cluster1 ++ weight: 50 ++ - name: cluster2 ++ weight: 50 ++ total_weight: 100 ++ inline_cluster_specifier_plugin: ++ extension: ++ name: test2 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test2 ++ - match: ++ prefix: "/bar" ++ route: ++ weighted_clusters: ++ clusters: ++ - name: cluster1 ++ weight: 50 ++ - name: cluster2 ++ weight: 50 ++ total_weight: 100 ++ inline_cluster_specifier_plugin: ++ extension: ++ name: test3 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test3 ++ )EOF"; ++ ++ NiceMock factory; ++ Registry::InjectFactory registered(factory); ++ ++ auto mock_cluster_specifier_plugin_1 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_2 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_3 = std::make_shared>(); ++ ++ factory_context_.cluster_manager_.initializeClusters({"cluster1", "cluster2"}, {}); ++ ++ EXPECT_CALL(factory, createClusterSpecifierPlugin(_, _)) ++ .WillRepeatedly(Invoke( ++ [mock_cluster_specifier_plugin_1, mock_cluster_specifier_plugin_2, ++ mock_cluster_specifier_plugin_3]( ++ const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext&) -> ClusterSpecifierPluginSharedPtr { ++ const auto& typed_config = dynamic_cast(config); ++ if (auto iter = typed_config.fields().find("a"); iter == typed_config.fields().end()) { ++ return nullptr; ++ } else if (iter->second.string_value() == "test1") { ++ return mock_cluster_specifier_plugin_1; ++ } else if (iter->second.string_value() == "test2") { ++ return mock_cluster_specifier_plugin_2; ++ } else if (iter->second.string_value() == "test3") { ++ return mock_cluster_specifier_plugin_3; ++ } ++ return nullptr; ++ })); ++ ++ NiceMock stream_info; ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ ++ auto mock_route = std::make_shared>(); ++ ++ EXPECT_CALL(*mock_cluster_specifier_plugin_2, route(_, _)).WillOnce(Return(mock_route)); ++ EXPECT_EQ(mock_route.get(), config.route(genHeaders("some_cluster", "/foo", "GET"), 0).get()); ++ ++ EXPECT_CALL(*mock_cluster_specifier_plugin_3, route(_, _)).WillOnce(Return(mock_route)); ++ EXPECT_EQ(mock_route.get(), config.route(genHeaders("some_cluster", "/bar", "GET"), 0).get()); ++} ++#endif ++ ++TEST_F(RouteMatcherTest, UnknownClusterSpecifierPluginName) { ++ const std::string yaml = R"EOF( ++cluster_specifier_plugins: ++- extension: ++ name: test1 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test1 ++- extension: ++ name: test2 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test2 ++- extension: ++ name: test3 ++ typed_config: ++ "@type": type.googleapis.com/google.protobuf.Struct ++ value: ++ a: test3 ++virtual_hosts: ++- name: local_service ++ domains: ++ - "*" ++ routes: ++ - match: ++ prefix: "/foo" ++ route: ++ cluster_specifier_plugin: test2 ++ - match: ++ prefix: "/bar" ++ route: ++ # Unknown cluster specifier plugin name. ++ cluster_specifier_plugin: test4 ++ )EOF"; ++ ++ NiceMock factory; ++ Registry::InjectFactory registered(factory); ++ ++ auto mock_cluster_specifier_plugin_1 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_2 = std::make_shared>(); ++ auto mock_cluster_specifier_plugin_3 = std::make_shared>(); ++ ++ EXPECT_CALL(factory, createClusterSpecifierPlugin(_, _)) ++ .WillRepeatedly(Invoke( ++ [mock_cluster_specifier_plugin_1, mock_cluster_specifier_plugin_2, ++ mock_cluster_specifier_plugin_3]( ++ const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext&) -> ClusterSpecifierPluginSharedPtr { ++ const auto& typed_config = dynamic_cast(config); ++ if (auto iter = typed_config.fields().find("a"); iter == typed_config.fields().end()) { ++ return nullptr; ++ } else if (iter->second.string_value() == "test1") { ++ return mock_cluster_specifier_plugin_1; ++ } else if (iter->second.string_value() == "test2") { ++ return mock_cluster_specifier_plugin_2; ++ } else if (iter->second.string_value() == "test3") { ++ return mock_cluster_specifier_plugin_3; ++ } ++ return nullptr; ++ })); ++ ++ NiceMock stream_info; ++ EXPECT_THROW_WITH_MESSAGE( ++ TestConfigImpl(parseRouteConfigurationFromYaml(yaml), factory_context_, true), EnvoyException, ++ "Unknown cluster specifier plugin name: test4 is used in the route"); ++} ++ + TEST_F(RouteMatcherTest, ContentType) { + const std::string yaml = R"EOF( + virtual_hosts: +@@ -7742,6 +8166,325 @@ virtual_hosts: + internal_redirect_policy.shouldRedirectForResponseCode(static_cast(200))); + } + ++#if defined(ALIMESH) ++TEST_F(RouteConfigurationV2, InternalActiveRedirectIsDisabledWhenNotSpecifiedInRouteAction) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [idle.lyft.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/regex" ++ route: ++ cluster: some-cluster ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("idle.lyft.com", "/regex", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_FALSE(internal_active_redirect_policy.enabled()); ++} ++ ++TEST_F(RouteConfigurationV2, DefaultInternalActiveRedirectPolicyIsSensible) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [idle.lyft.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/regex" ++ route: ++ cluster: some-cluster ++ internal_active_redirect_policy: ++ policies: ++ - redirect_url: "taobao.com" ++ redirect_response_codes: [404] ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("idle.lyft.com", "/regex", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_TRUE(internal_active_redirect_policy.enabled()); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(503))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(200))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(302))); ++ EXPECT_EQ(1, internal_active_redirect_policy.maxInternalRedirects()); ++ EXPECT_TRUE(internal_active_redirect_policy.predicates().empty()); ++ EXPECT_FALSE(internal_active_redirect_policy.isCrossSchemeRedirectAllowed()); ++ EXPECT_EQ("taobao.com", internal_active_redirect_policy.redirectUrl()); ++} ++ ++TEST_F(RouteConfigurationV2, InternalActiveRedirectPolicyDropsInvalidRedirectCode) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [idle.lyft.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/regex" ++ route: ++ cluster: some-cluster ++ internal_active_redirect_policy: ++ policies: ++ - redirect_url: "taobao.com" ++ redirect_response_codes: [301, 302, 303, 304, 307, 308, 503, 500, 404] ++ request_headers_to_add: ++ - header: ++ key: x-req-cluster ++ value: cluster1 ++ append: true ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("idle.lyft.com", "/regex", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_TRUE(internal_active_redirect_policy.enabled()); ++ // The 301, 302, 303, 307, 308 is invalid code. ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(301))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(302))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(303))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(307))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(308))); ++ // No configured code. ++ EXPECT_TRUE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(304))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(305))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(306))); ++ // The configured code. ++ EXPECT_TRUE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(503))); ++ EXPECT_TRUE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(500))); ++ EXPECT_TRUE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(404))); ++ ++ NiceMock stream_info; ++ Http::TestRequestHeaderMapImpl header_map{{":method", "POST"}}; ++ internal_active_redirect_policy.evaluateHeaders(header_map, &stream_info); ++ EXPECT_TRUE(header_map.has("x-req-cluster")); ++ EXPECT_FALSE(header_map.has("x-client-ip")); ++} ++ ++TEST_F(RouteConfigurationV2, InternalActiveRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [idle.lyft.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/regex" ++ route: ++ cluster: some-cluster ++ internal_active_redirect_policy: ++ policies: ++ - redirect_response_codes: [200, 301] ++ redirect_url_rewrite_regex: ++ pattern: ++ google_re2: {} ++ regex: "^/.+/(.+)$" ++ substitution: \1 ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("idle.lyft.com", "/regex", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_TRUE(internal_active_redirect_policy.enabled()); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(302))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(301))); ++ EXPECT_FALSE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(200))); ++} ++ ++TEST_F(RouteConfigurationV2, InternalActiveRedirectPolicyWithRedirectUrlRewriteRegex) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [idle.lyft.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/regex" ++ route: ++ cluster: some-cluster ++ internal_active_redirect_policy: ++ policies: ++ - redirect_response_codes: [200, 301] ++ redirect_url_rewrite_regex: ++ pattern: ++ google_re2: {} ++ regex: "^/.+/(.+)$" ++ substitution: \1 ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("idle.lyft.com", "/regex", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_TRUE(internal_active_redirect_policy.enabled()); ++ ++ std::string path("/rewrite-host-with-path-regex/envoyproxy.io"); ++ EXPECT_EQ("envoyproxy.io", internal_active_redirect_policy.redirectUrl(path)); ++} ++ ++TEST_F(RouteConfigurationV2, ++ InternalActiveRedirectPolicyWithRedirectUrlWithYoukuKrakenRewriteRegex) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [act.youku.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/yep/page/kraken/m_pre/i_just_test" ++ route: ++ cluster: some-cluster ++ internal_active_redirect_policy: ++ policies: ++ - redirect_response_codes: [503] ++ redirect_url_rewrite_regex: ++ pattern: ++ google_re2: {} ++ regex: (\W|^)kraken ++ substitution: test ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("act.youku.com", "/yep/page/kraken/m_pre/i_just_test", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_TRUE(internal_active_redirect_policy.enabled()); ++ ++ std::string path("/yep/page/kraken/m_pre/i_just_test"); ++ EXPECT_EQ("/yep/pagetest/m_pre/i_just_test", internal_active_redirect_policy.redirectUrl(path)); ++} ++ ++TEST_F(RouteConfigurationV2, InternalActiveRedirectPolicyWithRedirectUrlHostRewrite) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [act.youku.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/yep/i_just_test" ++ route: ++ cluster: some-cluster ++ internal_active_redirect_policy: ++ policies: ++ - redirect_response_codes: [503] ++ redirect_url: /yep/page/kraken/m_pre/i_just_test ++ host_rewrite_literal: taobao.com ++ ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("act.youku.com", "/yep/i_just_test", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_TRUE(internal_active_redirect_policy.enabled()); ++ ++ EXPECT_EQ("/yep/page/kraken/m_pre/i_just_test", internal_active_redirect_policy.redirectUrl()); ++ ++ NiceMock stream_info; ++ Http::TestRequestHeaderMapImpl header_map{{":method", "POST"}}; ++ internal_active_redirect_policy.evaluateHeaders(header_map, &stream_info); ++ EXPECT_EQ("taobao.com", header_map.getHostValue()); ++} ++ ++TEST_F(RouteConfigurationV2, InternalActiveRedirectPolicyWithMultiPolicies) { ++ const std::string yaml = R"EOF( ++virtual_hosts: ++ - name: regex ++ domains: [act.youku.com] ++ routes: ++ - match: ++ safe_regex: ++ google_re2: {} ++ regex: "/yep/i_just_test" ++ route: ++ cluster: some-cluster ++ internal_active_redirect_policy: ++ policies: ++ - redirect_response_codes: [503] ++ redirect_url: /yep/page/kraken/m_pre/i_just_test ++ host_rewrite_literal: taobao.com ++ - redirect_response_codes: [505] ++ redirect_url: /yep/page/kraken/m_pre/i_just_test_505 ++ host_rewrite_literal: taobao.com ++ - redirect_response_codes: [404] ++ redirect_url: /yep/page/kraken/m_pre/i_just_test_404 ++ host_rewrite_literal: taobao.com ++ )EOF"; ++ ++ factory_context_.cluster_manager_.initializeClusters({"some-cluster"}, {}); ++ TestConfigImpl config(parseRouteConfigurationFromYaml(yaml), factory_context_, true); ++ Http::TestRequestHeaderMapImpl headers = ++ genRedirectHeaders("act.youku.com", "/yep/i_just_test", true, false); ++ const auto& internal_active_redirect_policy = ++ config.route(headers, 0)->routeEntry()->internalActiveRedirectPolicy(); ++ EXPECT_TRUE(internal_active_redirect_policy.enabled()); ++ ++ EXPECT_EQ("/yep/page/kraken/m_pre/i_just_test", internal_active_redirect_policy.redirectUrl()); ++ ++ NiceMock stream_info; ++ Http::TestRequestHeaderMapImpl header_map{{":method", "POST"}}; ++ internal_active_redirect_policy.evaluateHeaders(header_map, &stream_info); ++ EXPECT_EQ("taobao.com", header_map.getHostValue()); ++ ++ EXPECT_TRUE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(404))); ++ EXPECT_EQ("/yep/page/kraken/m_pre/i_just_test_404", ++ internal_active_redirect_policy.redirectUrl()); ++ ++ EXPECT_TRUE( ++ internal_active_redirect_policy.shouldRedirectForResponseCode(static_cast(505))); ++ EXPECT_EQ("/yep/page/kraken/m_pre/i_just_test_505", ++ internal_active_redirect_policy.redirectUrl()); ++} ++ ++#endif ++ + class PerFilterConfigsTest : public testing::Test, public ConfigImplTestBase { + public: + PerFilterConfigsTest() +@@ -8417,6 +9160,23 @@ virtual_hosts: + }, + genHeaders("bat.com", "/", "GET")); + EXPECT_NE(nullptr, dynamic_cast(accepted_route.get())); ++#if defined(ALIMESH) ++ EXPECT_EQ(Http::Code::MovedPermanently, ++ dynamic_cast(accepted_route.get()) ++ ->directResponseEntry() ++ ->responseCode()); ++ RouteConstSharedPtr accepted_route_post = config.route( ++ [](RouteConstSharedPtr, RouteEvalStatus) -> RouteMatchStatus { ++ ADD_FAILURE() << "RouteCallback should not be invoked since there are no matching " ++ "route to override"; ++ return RouteMatchStatus::Continue; ++ }, ++ genHeaders("bat.com", "/", "POST")); ++ EXPECT_EQ(Http::Code::PermanentRedirect, ++ dynamic_cast(accepted_route_post.get()) ++ ->directResponseEntry() ++ ->responseCode()); ++#endif + } + + TEST_F(RouteMatchOverrideTest, NullRouteOnRequireTlsInternal) { +diff --git a/test/common/router/retry_state_impl_test.cc b/test/common/router/retry_state_impl_test.cc +index 1640683d81..f2199dda95 100644 +--- a/test/common/router/retry_state_impl_test.cc ++++ b/test/common/router/retry_state_impl_test.cc +@@ -44,9 +44,10 @@ public: + } + + void setup(Http::RequestHeaderMap& request_headers) { +- state_ = RetryStateImpl::create(policy_, request_headers, cluster_, &virtual_cluster_, runtime_, +- random_, dispatcher_, test_time_.timeSystem(), +- Upstream::ResourcePriority::Default); ++ ++ state_ = RetryStateImpl::create(policy_, request_headers, cluster_, &virtual_cluster_, ++ route_stats_context_, runtime_, random_, dispatcher_, ++ test_time_.timeSystem(), Upstream::ResourcePriority::Default); + } + + void expectTimerCreateAndEnable() { +@@ -131,6 +132,11 @@ public: + NiceMock policy_; + NiceMock cluster_; + TestVirtualCluster virtual_cluster_; ++ Stats::IsolatedStoreImpl stats_store_; ++ Stats::StatNameManagedStorage stat_name_{"fake_route", stats_store_.symbolTable()}; ++ RouteStatNames stat_names_{stats_store_.symbolTable()}; ++ RouteStatsContext route_stats_context_{stats_store_, stat_names_, stat_name_.statName(), ++ "fake_route"}; + NiceMock runtime_; + NiceMock random_; + Event::MockDispatcher dispatcher_; +@@ -168,10 +174,14 @@ TEST_F(RouterRetryStateImplTest, PolicyRefusedStream) { + + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_.value()); + } + ++ ++ + TEST_F(RouterRetryStateImplTest, Policy5xxResetOverflow) { + Http::TestRequestHeaderMapImpl request_headers{{"x-envoy-retry-on", "5xx"}}; + setup(request_headers); +@@ -193,8 +203,10 @@ TEST_F(RouterRetryStateImplTest, Policy5xxRemoteReset) { + + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + } + + TEST_F(RouterRetryStateImplTest, Policy5xxRemote503) { +@@ -275,8 +287,10 @@ TEST_F(RouterRetryStateImplTest, PolicyGatewayErrorRemoteReset) { + + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + } + + TEST_F(RouterRetryStateImplTest, PolicyGrpcCancelled) { +@@ -317,8 +331,10 @@ TEST_F(RouterRetryStateImplTest, Policy5xxRemote200RemoteReset) { + + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + } + + TEST_F(RouterRetryStateImplTest, RuntimeGuard) { +@@ -666,8 +682,10 @@ TEST_F(RouterRetryStateImplTest, PolicyResetRemoteReset) { + + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + } + + TEST_F(RouterRetryStateImplTest, PolicyLimitedByRequestHeaders) { +@@ -746,8 +764,10 @@ TEST_F(RouterRetryStateImplTest, RouteConfigNoRetriesAllowed) { + + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(0UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(0UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + } + + TEST_F(RouterRetryStateImplTest, RouteConfigNoHeaderConfig) { +@@ -773,6 +793,7 @@ TEST_F(RouterRetryStateImplTest, NoAvailableRetries) { + EXPECT_EQ(RetryStatus::NoOverflow, state_->shouldRetryReset(connect_failure_, callback_)); + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_overflow_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_overflow_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_overflow_.value()); + } + + TEST_F(RouterRetryStateImplTest, MaxRetriesHeader) { +@@ -809,6 +830,9 @@ TEST_F(RouterRetryStateImplTest, MaxRetriesHeader) { + EXPECT_EQ(3UL, virtual_cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(0UL, virtual_cluster_.stats().upstream_rq_retry_success_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(3UL, route_stats_context_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(0UL, route_stats_context_.stats().upstream_rq_retry_success_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + } + + TEST_F(RouterRetryStateImplTest, Backoff) { +@@ -844,6 +868,8 @@ TEST_F(RouterRetryStateImplTest, Backoff) { + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_success_.value()); + EXPECT_EQ(3UL, virtual_cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_success_.value()); ++ EXPECT_EQ(3UL, route_stats_context_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_success_.value()); + EXPECT_EQ(0UL, cluster_.circuit_breakers_stats_.rq_retry_open_.value()); + } + +@@ -1094,8 +1120,10 @@ TEST_F(RouterRetryStateImplTest, ZeroMaxRetriesHeader) { + + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(1UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(0UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(0UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(0UL, route_stats_context_.stats().upstream_rq_retry_.value()); + } + + // Check that if there are 0 remaining retries available but we get +@@ -1114,8 +1142,10 @@ TEST_F(RouterRetryStateImplTest, NoPreferredOverLimitExceeded) { + + EXPECT_EQ(0UL, cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(0UL, virtual_cluster_.stats().upstream_rq_retry_limit_exceeded_.value()); ++ EXPECT_EQ(0UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + EXPECT_EQ(1UL, cluster_.stats().upstream_rq_retry_.value()); + EXPECT_EQ(1UL, virtual_cluster_.stats().upstream_rq_retry_.value()); ++ EXPECT_EQ(0UL, route_stats_context_.stats().upstream_rq_retry_limit_exceeded_.value()); + } + + TEST_F(RouterRetryStateImplTest, BudgetAvailableRetries) { +diff --git a/test/common/router/router_2_test.cc b/test/common/router/router_2_test.cc +index 4b6b9ddd72..26930235fe 100644 +--- a/test/common/router/router_2_test.cc ++++ b/test/common/router/router_2_test.cc +@@ -336,6 +336,9 @@ TEST_F(RouterTestChildSpan, BasicFlow) { + EXPECT_CALL(callbacks_.active_span_, spawnChild_(_, "router fake_cluster egress", _)) + .WillOnce(Return(child_span)); + EXPECT_CALL(callbacks_, tracingConfig()); ++#if defined(ALIMESH) ++ EXPECT_CALL(*child_span, setTag(Eq(Tracing::Tags::get().PeerIpv4), Eq("10.0.0.5"))); ++#endif + router_.decodeHeaders(headers, true); + EXPECT_EQ(1U, + callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); +@@ -382,6 +385,9 @@ TEST_F(RouterTestChildSpan, ResetFlow) { + EXPECT_CALL(callbacks_.active_span_, spawnChild_(_, "router fake_cluster egress", _)) + .WillOnce(Return(child_span)); + EXPECT_CALL(callbacks_, tracingConfig()); ++#if defined(ALIMESH) ++ EXPECT_CALL(*child_span, setTag(Eq(Tracing::Tags::get().PeerIpv4), Eq("10.0.0.5"))); ++#endif + router_.decodeHeaders(headers, true); + EXPECT_EQ(1U, + callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); +@@ -432,6 +438,9 @@ TEST_F(RouterTestChildSpan, CancelFlow) { + EXPECT_CALL(callbacks_.active_span_, spawnChild_(_, "router fake_cluster egress", _)) + .WillOnce(Return(child_span)); + EXPECT_CALL(callbacks_, tracingConfig()); ++#if defined(ALIMESH) ++ EXPECT_CALL(*child_span, setTag(Eq(Tracing::Tags::get().PeerIpv4), Eq("10.0.0.5"))); ++#endif + router_.decodeHeaders(headers, true); + EXPECT_EQ(1U, + callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); +@@ -479,6 +488,9 @@ TEST_F(RouterTestChildSpan, ResetRetryFlow) { + EXPECT_CALL(callbacks_.active_span_, spawnChild_(_, "router fake_cluster egress", _)) + .WillOnce(Return(child_span_1)); + EXPECT_CALL(callbacks_, tracingConfig()); ++#if defined(ALIMESH) ++ EXPECT_CALL(*child_span_1, setTag(Eq(Tracing::Tags::get().PeerIpv4), Eq("10.0.0.5"))); ++#endif + router_.decodeHeaders(headers, true); + EXPECT_EQ(1U, + callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); +@@ -519,6 +531,9 @@ TEST_F(RouterTestChildSpan, ResetRetryFlow) { + EXPECT_CALL(callbacks_.active_span_, spawnChild_(_, "router fake_cluster egress", _)) + .WillOnce(Return(child_span_2)); + EXPECT_CALL(callbacks_, tracingConfig()); ++#if defined(ALIMESH) ++ EXPECT_CALL(*child_span_2, setTag(Eq(Tracing::Tags::get().PeerIpv4), Eq("10.0.0.5"))); ++#endif + EXPECT_CALL(*child_span_2, setTag(Eq(Tracing::Tags::get().RetryCount), Eq("1"))); + + router_.retry_state_->callback_(); +diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc +index 1ff5661d20..ccd19e7ea9 100644 +--- a/test/common/router/router_test.cc ++++ b/test/common/router/router_test.cc +@@ -55,6 +55,7 @@ using testing::AtLeast; + using testing::Eq; + using testing::InSequence; + using testing::Invoke; ++using testing::InvokeWithoutArgs; + using testing::MockFunction; + using testing::NiceMock; + using testing::Property; +@@ -323,7 +324,7 @@ TEST_F(RouterTest, MissingRequiredHeaders) { + sendLocalReply(Http::Code::ServiceUnavailable, + testing::Eq("missing required header: :method"), _, _, + "filter_removed_required_request_headers{missing required header: :method}")) +- .WillOnce(testing::InvokeWithoutArgs([] {})); ++ .WillOnce(InvokeWithoutArgs([] {})); + router_.decodeHeaders(headers, true); + router_.onDestroy(); + } +@@ -3775,8 +3776,7 @@ TEST_F(RouterTest, RetryUpstreamResetResponseStarted) { + // Normally, sendLocalReply will actually send the reply, but in this case the + // HCM will detect the headers have already been sent and not route through + // the encoder again. +- EXPECT_CALL(callbacks_, sendLocalReply(_, _, _, _, _)).WillOnce(testing::InvokeWithoutArgs([] { +- })); ++ EXPECT_CALL(callbacks_, sendLocalReply(_, _, _, _, _)).WillOnce(InvokeWithoutArgs([] {})); + encoder1.stream_.resetStream(Http::StreamResetReason::RemoteReset); + // For normal HTTP, once we have a 200 we consider this a success, even if a + // later reset occurs. +@@ -4736,6 +4736,33 @@ TEST_F(RouterTest, HttpInternalRedirectSucceeded) { + .value()); + } + ++TEST_F(RouterTest, HttpInternalRedirectMatchedToDirectResponseSucceeded) { ++ NiceMock direct_response; ++ std::string route_name("route-test-name"); ++ EXPECT_CALL(direct_response, routeName()).WillOnce(ReturnRef(route_name)); ++ ++ enableRedirects(); ++ sendRequest(); ++ EXPECT_CALL(callbacks_, clearRouteCache()).WillOnce(InvokeWithoutArgs([&]() -> void { ++ // Direct message route should be matched after internal redirect ++ EXPECT_CALL(*callbacks_.route_, routeEntry()).WillRepeatedly(Return(nullptr)); ++ EXPECT_CALL(*callbacks_.route_, directResponseEntry()).WillRepeatedly(Return(&direct_response)); ++ })); ++ EXPECT_CALL(callbacks_, recreateStream(_)).WillOnce(Return(true)); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), false); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_succeeded_total") ++ .value()); ++ ++ // In production, the HCM recreateStream would have called this. ++ router_.onDestroy(); ++ EXPECT_EQ(1, callbacks_.streamInfo() ++ .filterState() ++ ->getDataMutable("num_internal_redirects") ++ .value()); ++} ++ + TEST_F(RouterTest, InternalRedirectStripsFragment) { + enableRedirects(); + default_request_headers_.setForwardedProto("http"); +@@ -4821,6 +4848,264 @@ TEST_F(RouterTest, CrossSchemeRedirectAllowedByPolicy) { + router_.onDestroy(); + } + ++#if defined(ALIMESH) ++TEST_F(RouterTest, InternalActiveRedirectRejectedWhenReachingMaxInternalRedirect) { ++ enableActiveRedirects("http://www.foo.com", 3); ++ setNumPreviousRedirect(3); ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(active_redirect_headers_), false); ++ ++ Buffer::OwnedImpl data("1234567890"); ++ response_decoder_->decodeData(data, true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++ EXPECT_EQ(1UL, ++ stats_store_.counter("test.passthrough_internal_redirect_too_many_redirects").value()); ++} ++ ++TEST_F(RouterTest, InternalActiveRedirectRejectedWithEmptyLocation) { ++ enableActiveRedirects(""); ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), false); ++ ++ Buffer::OwnedImpl data("1234567890"); ++ response_decoder_->decodeData(data, true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++ EXPECT_EQ(1UL, stats_store_.counter("test.passthrough_internal_redirect_bad_location").value()); ++} ++ ++TEST_F(RouterTest, InternalActiveRedirectRejectedWithInvalidLocation) { ++ enableActiveRedirects("h"); ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), false); ++ ++ Buffer::OwnedImpl data("1234567890"); ++ response_decoder_->decodeData(data, true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++ EXPECT_EQ(1UL, stats_store_.counter("test.passthrough_internal_redirect_bad_location").value()); ++} ++ ++TEST_F(RouterTest, InternalActiveRedirectRejectedWithoutCompleteRequest) { ++ enableActiveRedirects("http://www.foo.com", 3); ++ ++ sendRequest(false); ++ ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), false); ++ ++ Buffer::OwnedImpl data("1234567890"); ++ response_decoder_->decodeData(data, true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++} ++ ++TEST_F(RouterTest, InternalActiveRedirectRejectedWithoutLocation) { ++ enableActiveRedirects(""); ++ ++ sendRequest(); ++ ++ redirect_headers_->removeLocation(); ++ ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), false); ++ Buffer::OwnedImpl data("1234567890"); ++ response_decoder_->decodeData(data, true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++} ++ ++TEST_F(RouterTest, InternalActiveRedirectRejectedWithBody) { ++ enableActiveRedirects("http://www.foo.com"); ++ ++ sendRequest(); ++ ++ Buffer::InstancePtr body_data(new Buffer::OwnedImpl("random_fake_data")); ++ EXPECT_CALL(callbacks_, decodingBuffer()).WillRepeatedly(Return(body_data.get())); ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), false); ++ Buffer::OwnedImpl data("1234567890"); ++ response_decoder_->decodeData(data, true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++} ++ ++TEST_F(RouterTest, CrossSchemeActiveRedirectRejectedByPolicy) { ++ enableActiveRedirects("https://www.foo.com"); ++ ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++ EXPECT_EQ(1UL, stats_store_.counter("test.passthrough_internal_redirect_unsafe_scheme").value()); ++} ++ ++TEST_F(RouterTest, InternalActiveRedirectRejectedByPredicate) { ++ enableActiveRedirects("http://www.foo.com/some/path"); ++ sendRequest(); ++ ++ auto mock_predicate = std::make_shared>(); ++ ++ EXPECT_CALL(callbacks_, clearRouteCache()); ++ EXPECT_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, predicates()) ++ .WillOnce(Return(std::vector({mock_predicate}))); ++ EXPECT_CALL(*mock_predicate, acceptTargetRoute(_, _, _, _)).WillOnce(Return(false)); ++ ON_CALL(*mock_predicate, name()).WillByDefault(Return("mock_predicate")); ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), true); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_failed_total") ++ .value()); ++ EXPECT_EQ(1UL, stats_store_.counter("test.passthrough_internal_redirect_predicate").value()); ++ ++ // Make sure the original host/path is preserved. ++ EXPECT_EQ("host", default_request_headers_.getHostValue()); ++ EXPECT_EQ("/", default_request_headers_.getPathValue()); ++ // Make sure x-envoy-original-url is not set for unsuccessful redirect. ++ EXPECT_EQ(nullptr, default_request_headers_.EnvoyOriginalUrl()); ++} ++ ++TEST_F(RouterTest, HttpInternalActiveRedirectSucceeded) { ++ enableActiveRedirects("http://www.foo.com/some/path", 3); ++ setNumPreviousRedirect(2); ++ default_request_headers_.setForwardedProto("http"); ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, clearRouteCache()); ++ EXPECT_CALL(callbacks_, recreateStream(_)).WillOnce(Return(true)); ++ response_decoder_->decodeHeaders(std::move(redirect_headers_), false); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_succeeded_total") ++ .value()); ++ ++ // In production, the HCM recreateStream would have called this. ++ router_.onDestroy(); ++ EXPECT_EQ(3, callbacks_.streamInfo() ++ .filterState() ++ ->getDataMutable("num_internal_redirects") ++ .value()); ++} ++ ++TEST_F(RouterTest, HttpsInternalActiveRedirectSucceeded) { ++ auto ssl_connection = std::make_shared(); ++ enableActiveRedirects("https://www.foo.com", 3); ++ setNumPreviousRedirect(1); ++ default_request_headers_.setScheme("https"); ++ ++ sendRequest(); ++ ++ EXPECT_CALL(connection_, ssl()).WillOnce(Return(ssl_connection)); ++ EXPECT_CALL(callbacks_, clearRouteCache()); ++ EXPECT_CALL(callbacks_, recreateStream(_)).WillOnce(Return(true)); ++ response_decoder_->decodeHeaders(std::move(active_redirect_headers_), false); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_succeeded_total") ++ .value()); ++ ++ // In production, the HCM recreateStream would have called this. ++ router_.onDestroy(); ++} ++ ++TEST_F(RouterTest, CrossSchemeActiveRedirectAllowedByPolicy) { ++ auto ssl_connection = std::make_shared(); ++ enableActiveRedirects("http://www.redirect-url.com", 1); ++ default_request_headers_.setScheme("https"); ++ ++ sendRequest(); ++ ++ EXPECT_CALL(connection_, ssl()).WillOnce(Return(ssl_connection)); ++ EXPECT_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, ++ isCrossSchemeRedirectAllowed()) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(callbacks_, clearRouteCache()); ++ EXPECT_CALL(callbacks_, recreateStream(_)).WillOnce(Return(true)); ++ response_decoder_->decodeHeaders(std::move(active_redirect_headers_), false); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_succeeded_total") ++ .value()); ++ EXPECT_EQ("www.redirect-url.com", std::string(default_request_headers_.getHostValue())); ++ // In production, the HCM recreateStream would have called this. ++ router_.onDestroy(); ++} ++ ++TEST_F(RouterTest, UseOriginalHost) { ++ auto ssl_connection = std::make_shared(); ++ enableActiveRedirects("http://www.redirect-url.com", 1, true); ++ default_request_headers_.setHost("original-test-host.com"); ++ ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, clearRouteCache()); ++ EXPECT_CALL(callbacks_, recreateStream(_)).WillOnce(Return(true)); ++ response_decoder_->decodeHeaders(std::move(active_redirect_headers_), false); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_succeeded_total") ++ .value()); ++ EXPECT_EQ("original-test-host.com", std::string(default_request_headers_.getHostValue())); ++ // In production, the HCM recreateStream would have called this. ++ router_.onDestroy(); ++} ++ ++TEST_F(RouterTest, ForcedAddHeaderBeforeRouteMatcher) { ++ auto ssl_connection = std::make_shared(); ++ enableActiveRedirects("http://www.redirect-url.com", 1, false, true); ++ ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, clearRouteCache()); ++ EXPECT_CALL(callbacks_, recreateStream(_)).WillOnce(Return(true)); ++ response_decoder_->decodeHeaders(std::move(active_redirect_headers_), false); ++ EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_succeeded_total") ++ .value()); ++ EXPECT_EQ(true, default_request_headers_.has("test_added_header")); ++ // In production, the HCM recreateStream would have called this. ++ router_.onDestroy(); ++} ++ ++TEST_F(RouterTest, ForcedAddHeaderBeforeRouteMatcherWithRouteFailure) { ++ auto ssl_connection = std::make_shared(); ++ enableActiveRedirects("http://www.redirect-url.com", 1, false, true); ++ ++ sendRequest(); ++ ++ EXPECT_CALL(callbacks_, clearRouteCache()); ++ EXPECT_CALL(callbacks_, route()).WillOnce(Return(nullptr));; ++ EXPECT_CALL(callbacks_, recreateStream(_)).Times(0); ++ response_decoder_->decodeHeaders(std::move(active_redirect_headers_), false); ++ EXPECT_EQ(0U, cm_.thread_local_cluster_.cluster_.info_->stats_store_ ++ .counter("upstream_internal_redirect_succeeded_total") ++ .value()); ++ EXPECT_EQ(true, default_request_headers_.has("test_added_header")); ++ // In production, the HCM recreateStream would have called this. ++ router_.onDestroy(); ++} ++#endif ++ + TEST_F(RouterTest, Shadow) { + ShadowPolicyPtr policy = std::make_unique("foo", "bar"); + callbacks_.route_->route_entry_.shadow_policies_.push_back(std::move(policy)); +@@ -5946,6 +6231,9 @@ TEST_F(RouterTest, CanaryStatusTrue) { + Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-alt-stat-name", "alt_stat"}, + {"x-envoy-internal", "true"}}; + HttpTestUtility::addDefaultHeaders(headers); ++ const absl::optional virtual_cluster_name = ++ absl::optional("fake_virtual_cluster"); ++ EXPECT_CALL(callbacks_.stream_info_, setVirtualClusterName(virtual_cluster_name)); + router_.decodeHeaders(headers, true); + EXPECT_EQ(1U, + callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); +@@ -5983,6 +6271,9 @@ TEST_F(RouterTest, CanaryStatusFalse) { + Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-alt-stat-name", "alt_stat"}, + {"x-envoy-internal", "true"}}; + HttpTestUtility::addDefaultHeaders(headers); ++ const absl::optional virtual_cluster_name = ++ absl::optional("fake_virtual_cluster"); ++ EXPECT_CALL(callbacks_.stream_info_, setVirtualClusterName(virtual_cluster_name)); + router_.decodeHeaders(headers, true); + EXPECT_EQ(1U, + callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); +@@ -5999,7 +6290,11 @@ TEST_F(RouterTest, CanaryStatusFalse) { + .value()); + } + ++#if defined(ALIMESH) ++TEST_F(RouterTest, DISABLED_AutoHostRewriteEnabled) { ++#else + TEST_F(RouterTest, AutoHostRewriteEnabled) { ++#endif + NiceMock encoder; + std::string req_host{"foo.bar.com"}; + +@@ -6011,6 +6306,7 @@ TEST_F(RouterTest, AutoHostRewriteEnabled) { + Http::TestRequestHeaderMapImpl outgoing_headers; + HttpTestUtility::addDefaultHeaders(outgoing_headers); + outgoing_headers.setHost(cm_.thread_local_cluster_.conn_pool_.host_->hostname_); ++ outgoing_headers.setForwardedHost(req_host); + + EXPECT_CALL(callbacks_.route_->route_entry_, timeout()) + .WillOnce(Return(std::chrono::milliseconds(0))); +@@ -6036,6 +6332,7 @@ TEST_F(RouterTest, AutoHostRewriteEnabled) { + EXPECT_EQ(host_address_, host->address()); + })); + EXPECT_CALL(callbacks_.route_->route_entry_, autoHostRewrite()).WillOnce(Return(true)); ++ EXPECT_CALL(callbacks_.route_->route_entry_, appendXfh()).WillOnce(Return(true)); + router_.decodeHeaders(incoming_headers, true); + EXPECT_EQ(1U, + callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); +diff --git a/test/common/router/router_test_base.cc b/test/common/router/router_test_base.cc +index dc598c6e4f..7acb133787 100644 +--- a/test/common/router/router_test_base.cc ++++ b/test/common/router/router_test_base.cc +@@ -250,6 +250,44 @@ void RouterTestBase::setNumPreviousRedirect(uint32_t num_previous_redirects) { + StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Request); + } + ++#if defined(ALIMESH) ++void RouterTestBase::enableActiveRedirects(std::string redirect_url, ++ uint32_t max_internal_redirects, ++ bool forced_use_original_host, ++ bool forced_add_header_before_route_matcher) { ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, enabled()) ++ .WillByDefault(Return(true)); ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, ++ shouldRedirectForResponseCode(_)) ++ .WillByDefault(Return(true)); ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, maxInternalRedirects()) ++ .WillByDefault(Return(max_internal_redirects)); ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, ++ isCrossSchemeRedirectAllowed()) ++ .WillByDefault(Return(false)); ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, redirectUrl(_)) ++ .WillByDefault(Return(redirect_url)); ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, evaluateHeaders(_, _)) ++ .WillByDefault(Invoke([&](Http::HeaderMap& headers, const StreamInfo::StreamInfo*) -> void { ++ const Envoy::Http::LowerCaseString key("test_added_header"); ++ headers.addCopy(key, 1111); ++ })); ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, forcedUseOriginalHost()) ++ .WillByDefault(Return(forced_use_original_host)); ++ ON_CALL(callbacks_.route_->route_entry_.internal_active_redirect_policy_, ++ forcedAddHeaderBeforeRouteMatcher()) ++ .WillByDefault(Return(forced_add_header_before_route_matcher)); ++ ON_CALL(callbacks_, connection()).WillByDefault(Return(&connection_)); ++} ++ ++void RouterTestBase::setNumPreviousActiveRedirect(uint32_t num_previous_redirects) { ++ callbacks_.streamInfo().filterState()->setData( ++ "num_internal_redirects", ++ std::make_shared(num_previous_redirects), ++ StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Request); ++} ++#endif ++ + void RouterTestBase::setIncludeAttemptCountInRequest(bool include) { + ON_CALL(callbacks_.route_->route_entry_, includeAttemptCountInRequest()) + .WillByDefault(Return(include)); +diff --git a/test/common/router/router_test_base.h b/test/common/router/router_test_base.h +index 0dff3f0ade..e9c0e253ae 100644 +--- a/test/common/router/router_test_base.h ++++ b/test/common/router/router_test_base.h +@@ -30,8 +30,9 @@ public: + // Filter + RetryStatePtr createRetryState(const RetryPolicy&, Http::RequestHeaderMap&, + const Upstream::ClusterInfo&, const VirtualCluster*, +- Runtime::Loader&, Random::RandomGenerator&, Event::Dispatcher&, +- TimeSource&, Upstream::ResourcePriority) override { ++ RouteStatsContextOptRef, Runtime::Loader&, ++ Random::RandomGenerator&, Event::Dispatcher&, TimeSource&, ++ Upstream::ResourcePriority) override { + EXPECT_EQ(nullptr, retry_state_); + retry_state_ = new NiceMock(); + if (reject_all_hosts_) { +@@ -45,6 +46,16 @@ public: + return &downstream_connection_; + } + ++#if defined(ALIMESH) ++ Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& headers, ++ bool end_stream) override { ++ auto status = Filter::decodeHeaders(headers, end_stream); ++ // TODO: deletes the header and consider using custom headers. ++ headers.remove(Http::CustomHeaders::get().AliExtendedValues.TriStartTime); ++ return status; ++ } ++#endif ++ + NiceMock downstream_connection_; + MockRetryState* retry_state_{}; + bool reject_all_hosts_ = false; +@@ -79,6 +90,15 @@ public: + absl::optional host_address_header_name); + void testDoNotForward(absl::optional not_forwarded_header_name); + ++#if defined(ALIMESH) ++ void enableActiveRedirects(std::string redirect_url, uint32_t max_internal_redirects = 1, ++ bool forced_use_original_host = false, ++ bool forced_add_header_before_route_matcher = false); ++ void setNumPreviousActiveRedirect(uint32_t num_previous_redirects); ++ ++ Http::ResponseHeaderMapPtr active_redirect_headers_{ ++ new Http::TestResponseHeaderMapImpl{{":status", "502"}, {"location", "http://www.foo.com"}}}; ++#endif + Event::SimulatedTimeSystem test_time_; + std::string upstream_zone_{"to_az"}; + envoy::config::core::v3::Locality upstream_locality_; +diff --git a/test/common/router/router_upstream_log_test.cc b/test/common/router/router_upstream_log_test.cc +index 612790a8ee..802ac6cb05 100644 +--- a/test/common/router/router_upstream_log_test.cc ++++ b/test/common/router/router_upstream_log_test.cc +@@ -64,8 +64,9 @@ public: + // Filter + RetryStatePtr createRetryState(const RetryPolicy&, Http::RequestHeaderMap&, + const Upstream::ClusterInfo&, const VirtualCluster*, +- Runtime::Loader&, Random::RandomGenerator&, Event::Dispatcher&, +- TimeSource&, Upstream::ResourcePriority) override { ++ RouteStatsContextOptRef, Runtime::Loader&, ++ Random::RandomGenerator&, Event::Dispatcher&, TimeSource&, ++ Upstream::ResourcePriority) override { + EXPECT_EQ(nullptr, retry_state_); + retry_state_ = new NiceMock(); + return RetryStatePtr{retry_state_}; +@@ -75,6 +76,16 @@ public: + return &downstream_connection_; + } + ++#if defined(ALIMESH) ++ Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& headers, ++ bool end_stream) override { ++ auto status = Filter::decodeHeaders(headers, end_stream); ++ // TODO: deletes the header and consider using custom headers. ++ headers.remove(Http::CustomHeaders::get().AliExtendedValues.TriStartTime); ++ return status; ++ } ++#endif ++ + NiceMock downstream_connection_; + MockRetryState* retry_state_{}; + }; +diff --git a/test/common/signal/fatal_action_test.cc b/test/common/signal/fatal_action_test.cc +index 5565c592ee..7680b17eea 100644 +--- a/test/common/signal/fatal_action_test.cc ++++ b/test/common/signal/fatal_action_test.cc +@@ -66,6 +66,10 @@ protected: + int counter_ = 0; + }; + ++// A memory leak error occurred during test platform execution, which was verified to be a false ++// positive, so this unit test was shielded ++#if !defined(ALIMESH) ++ + TEST_F(FatalActionTest, ShouldNotBeAbleToRunActionsBeforeRegistration) { + // Call the actions + EXPECT_EQ(FatalErrorHandler::runSafeActions(), Status::ActionManagerUnset); +@@ -128,5 +132,7 @@ TEST_F(FatalActionTest, ShouldOnlyBeAbleToRunUnsafeActionsFromThreadThatRanSafeA + fatal_action_thread->join(); + } + ++#endif ++ + } // namespace FatalAction + } // namespace Envoy +diff --git a/test/common/stream_info/test_util.h b/test/common/stream_info/test_util.h +index 8026bde7de..7698048f46 100644 +--- a/test/common/stream_info/test_util.h ++++ b/test/common/stream_info/test_util.h +@@ -142,6 +142,14 @@ public: + last_downstream_tx_byte_sent_ = timeSystem().monotonicTime(); + } + ++ const absl::optional& virtualClusterName() const override { ++ return virtual_cluster_name_; ++ } ++ ++ void setVirtualClusterName(const absl::optional& name) { ++ virtual_cluster_name_ = name; ++ } ++ + void onRequestComplete() override { end_time_ = timeSystem().monotonicTime(); } + + void setUpstreamTiming(const Envoy::StreamInfo::UpstreamTiming& upstream_timing) override { +@@ -241,6 +249,7 @@ public: + bool health_check_request_{}; + std::string route_name_; + Network::Address::InstanceConstSharedPtr upstream_local_address_; ++ absl::optional virtual_cluster_name_; + Network::ConnectionInfoSetterSharedPtr downstream_connection_info_provider_{ + std::make_shared(nullptr, nullptr)}; + Ssl::ConnectionInfoConstSharedPtr downstream_connection_info_; +diff --git a/test/common/upstream/load_balancer_impl_test.cc b/test/common/upstream/load_balancer_impl_test.cc +index 78e6d1f746..97931f4265 100644 +--- a/test/common/upstream/load_balancer_impl_test.cc ++++ b/test/common/upstream/load_balancer_impl_test.cc +@@ -43,6 +43,9 @@ public: + return std::chrono::time_point_cast(edf_lb.latest_host_added_time_) + .time_since_epoch(); + } ++ static double slowStartMinWeightPercent(const EdfLoadBalancerBase& edf_lb) { ++ return edf_lb.slow_start_min_weight_percent_; ++ } + }; + + namespace { +@@ -1587,6 +1590,26 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartWithDefaultParams) { + const auto latest_host_added_time = + EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(*lb_)); + EXPECT_EQ(std::chrono::milliseconds(0), latest_host_added_time); ++ const auto slow_start_min_weight_percent = ++ EdfLoadBalancerBasePeer::slowStartMinWeightPercent(static_cast(*lb_)); ++ EXPECT_DOUBLE_EQ(slow_start_min_weight_percent, 0.1); ++} ++ ++TEST_P(RoundRobinLoadBalancerTest, SlowStartWithMinWeightPercent) { ++ round_robin_lb_config_.mutable_slow_start_config()->mutable_min_weight_percent()->set_value(30); ++ init(false); ++ const auto slow_start_window = ++ EdfLoadBalancerBasePeer::slowStartWindow(static_cast(*lb_)); ++ EXPECT_EQ(std::chrono::milliseconds(0), slow_start_window); ++ const auto aggression = ++ EdfLoadBalancerBasePeer::aggression(static_cast(*lb_)); ++ EXPECT_EQ(1.0, aggression); ++ const auto latest_host_added_time = ++ EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(*lb_)); ++ EXPECT_EQ(std::chrono::milliseconds(0), latest_host_added_time); ++ const auto slow_start_min_weight_percent = ++ EdfLoadBalancerBasePeer::slowStartMinWeightPercent(static_cast(*lb_)); ++ EXPECT_DOUBLE_EQ(slow_start_min_weight_percent, 0.3); + } + + TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWait) { +@@ -1623,7 +1646,7 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWait) { + EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(*lb_)); + EXPECT_EQ(std::chrono::milliseconds(62000), latest_host_added_time_ms); + +- // host2 is 12 secs in slow start, the weight is scaled with time factor 12 / 60 == 0.2. ++ // host2 is 12 secs in slow start, the weight is scaled with time factor max(12 / 60, 0.1) = 0.2. + simTime().advanceTimeWait(std::chrono::seconds(12)); + + // Recalculate weights. +@@ -1710,7 +1733,7 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartWaitForPassingHC) { + hostSet().runCallbacks({}, {}); + + // We expect 3:1 ratio, as host2 is in slow start mode, its weight is scaled with time factor +- // 5 / 10 == 0.5. ++ // max(6/10, 0.1) = 0.6. + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); +@@ -1754,7 +1777,7 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartWithRuntimeAggression) { + EXPECT_EQ(std::chrono::milliseconds(1000), latest_host_added_time_ms); + + // We should see 2:1:1 ratio, as hosts 2 and 3 are in slow start, their weights are scaled with +- // 0.5 factor. ++ // max(0.5,0.1)=0.5 factor. + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[2], lb_->chooseHost(nullptr)); +@@ -1774,8 +1797,8 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartWithRuntimeAggression) { + EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(*lb_)); + EXPECT_EQ(std::chrono::milliseconds(10000), latest_host_added_time_ms); + +- // We should see 1:1:1:0 ratio, as host 2 and 3 weight is scaled with (9/10)^(1/1.5)=0.93 factor, +- // host4 weight is 0.002. ++ // We should see 1:1:1:0 ratio, as host 2 and 3 weight is scaled with max((9/10)^(1/1.5),0.1)=0.93 ++ // factor, host4 weight is 1*max(0.002,0.1)=0.1. + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[2], lb_->chooseHost(nullptr)); +@@ -1783,7 +1806,8 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartWithRuntimeAggression) { + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[2], lb_->chooseHost(nullptr)); + +- // host4 is 9 seconds in slow start, it's weight is scaled with (9/10)^(1/1.5)=0.93 factor. ++ // host4 is 9 seconds in slow start, it's weight is scaled with max((9/10)^(1/1.5), 0.1)=0.93 ++ // factor. + simTime().advanceTimeWait(std::chrono::seconds(9)); + hostSet().runCallbacks({}, {}); + +@@ -1808,7 +1832,7 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWaitNonLinearAggression) { + hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", simTime())}; + hostSet().hosts_ = hostSet().healthy_hosts_; + simTime().advanceTimeWait(std::chrono::seconds(5)); +- // Host1 is 5 secs in slow start, its weight is scaled with (0.5/60)^(1/2)=0.28 factor. ++ // Host1 is 5 secs in slow start, its weight is scaled with max((5/60)^(1/2), 0.1)=0.28 factor. + hostSet().runCallbacks({}, {}); + + // Advance time, so that host1 is no longer in slow start. +@@ -1821,7 +1845,7 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWaitNonLinearAggression) { + + hostSet().healthy_hosts_.push_back(host2); + hostSet().hosts_ = hostSet().healthy_hosts_; +- // host2 weight is scaled with 0.004 factor. ++ // host2 weight is scaled with max((0.001/60)^(1/2), 0.1)=max(0.004, 0.1)=0.1 factor. + hostSet().runCallbacks(hosts_added, {}); + + // host2 is 6 secs in slow start. +@@ -1831,7 +1855,7 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWaitNonLinearAggression) { + hostSet().runCallbacks({}, {}); + + // We expect 3:1 ratio, as host2 is 6 secs in slow start mode and it's weight is scaled with +- // pow(0.1, 0.5)==0.31 factor. ++ // max(pow(0.1, 0.5), 0.1)=0.31 factor. + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); +@@ -1844,7 +1868,7 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWaitNonLinearAggression) { + hostSet().runCallbacks({}, {}); + + // We still expect 5:3 ratio, as host2 is in slow start mode and it's weight is scaled with +- // pow(0.43, 0.5)==0.65 factor. ++ // max(pow(0.43, 0.5), 0.1)=0.65 factor. + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); +@@ -1867,6 +1891,102 @@ TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWaitNonLinearAggression) { + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); + } + ++TEST_P(RoundRobinLoadBalancerTest, SlowStartNoWaitMinWeightPercent35) { ++ round_robin_lb_config_.mutable_slow_start_config()->mutable_slow_start_window()->set_seconds(60); ++ round_robin_lb_config_.mutable_slow_start_config()->mutable_min_weight_percent()->set_value(35); ++ simTime().advanceTimeWait(std::chrono::seconds(1)); ++ auto host1 = makeTestHost(info_, "tcp://127.0.0.1:80", simTime()); ++ host_set_.hosts_ = {host1}; ++ ++ init(true); ++ ++ // As no healthcheck is configured, hosts would enter slow start immediately. ++ HostVector empty; ++ HostVector hosts_added; ++ hosts_added.push_back(host1); ++ simTime().advanceTimeWait(std::chrono::seconds(5)); ++ hostSet().runCallbacks(hosts_added, empty); ++ auto latest_host_added_time_ms = ++ EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(*lb_)); ++ EXPECT_EQ(std::chrono::milliseconds(1000), latest_host_added_time_ms); ++ ++ // Advance time, so that host is no longer in slow start. ++ simTime().advanceTimeWait(std::chrono::seconds(56)); ++ ++ hosts_added.clear(); ++ auto host2 = makeTestHost(info_, "tcp://127.0.0.1:90", simTime()); ++ ++ hosts_added.push_back(host2); ++ ++ hostSet().healthy_hosts_ = {host1, host2}; ++ hostSet().hosts_ = hostSet().healthy_hosts_; ++ hostSet().runCallbacks(hosts_added, empty); ++ ++ latest_host_added_time_ms = ++ EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(*lb_)); ++ EXPECT_EQ(std::chrono::milliseconds(62000), latest_host_added_time_ms); ++ ++ // host2 is 12 secs in slow start, the weight is scaled with time factor max(12 / 60, 0.35) = ++ // 0.35. ++ simTime().advanceTimeWait(std::chrono::seconds(12)); ++ ++ // Recalculate weights. ++ hostSet().runCallbacks(empty, empty); ++ ++ // We expect 5:2 ratio, as host2 is in slow start mode and it's weight is scaled with ++ // 0.35 factor. ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[1,20/7] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[2,20/7] ++ EXPECT_EQ(hostSet().healthy_hosts_[1], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[3,20/7] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[3,40/7] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[4,40/7] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[5,40/7] ++ EXPECT_EQ(hostSet().healthy_hosts_[1], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[6,40/7] ++ ++ // host2 is 30 secs in slow start, the weight is scaled with time factor max(30 / 60, 0.35) == ++ // 0.5. ++ simTime().advanceTimeWait(std::chrono::seconds(18)); ++ ++ // Recalculate weights. ++ hostSet().runCallbacks(empty, empty); ++ ++ // We expect 2:1 ratio, as host2 is in slow start mode and it's weight is scaled with ++ // 0.5 factor. ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[1,2] ++ EXPECT_EQ(hostSet().healthy_hosts_[1], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[2,2] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[2,4] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[3,4] ++ EXPECT_EQ(hostSet().healthy_hosts_[1], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[4,4] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[4,6] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_->chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[5,6] ++ ++ // Advance time, so that there are no hosts in slow start. ++ simTime().advanceTimeWait(std::chrono::seconds(45)); ++ ++ // Recalculate weights. ++ hostSet().runCallbacks(empty, empty); ++ ++ // Now expect 1:1 ratio. ++ EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); ++ EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); ++ EXPECT_EQ(hostSet().healthy_hosts_[0], lb_->chooseHost(nullptr)); ++ EXPECT_EQ(hostSet().healthy_hosts_[1], lb_->chooseHost(nullptr)); ++} ++ + class LeastRequestLoadBalancerTest : public LoadBalancerTestBase { + public: + LeastRequestLoadBalancer lb_{ +@@ -2141,6 +2261,9 @@ TEST_P(LeastRequestLoadBalancerTest, SlowStartWithDefaultParams) { + const auto latest_host_added_time = + EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(lb_2)); + EXPECT_EQ(std::chrono::milliseconds(0), latest_host_added_time); ++ const auto slow_start_min_weight_percent = ++ EdfLoadBalancerBasePeer::slowStartMinWeightPercent(static_cast(lb_2)); ++ EXPECT_DOUBLE_EQ(slow_start_min_weight_percent, 0.1); + } + + TEST_P(LeastRequestLoadBalancerTest, SlowStartNoWait) { +@@ -2156,7 +2279,7 @@ TEST_P(LeastRequestLoadBalancerTest, SlowStartNoWait) { + hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", simTime())}; + hostSet().hosts_ = hostSet().healthy_hosts_; + simTime().advanceTimeWait(std::chrono::seconds(5)); +- // Host1 is 5 secs in slow start, its weight is scaled with (5/60)^1=0.08 factor. ++ // Host1 is 5 secs in slow start, its weight is scaled with max((5/60)^1, 0.1)=0.1 factor. + hostSet().runCallbacks({}, {}); + + auto latest_host_added_time = +@@ -2178,7 +2301,7 @@ TEST_P(LeastRequestLoadBalancerTest, SlowStartNoWait) { + EdfLoadBalancerBasePeer::latestHostAddedTime(static_cast(lb_2)); + EXPECT_EQ(std::chrono::milliseconds(62000), latest_host_added_time); + +- // host2 is 20 secs in slow start, the weight is scaled with time factor 20 / 60 == 0.16. ++ // host2 is 20 secs in slow start, the weight is scaled with time factor max(20/60, 0.1) = 0.16. + simTime().advanceTimeWait(std::chrono::seconds(10)); + + // Recalculate weights. +@@ -2194,7 +2317,7 @@ TEST_P(LeastRequestLoadBalancerTest, SlowStartNoWait) { + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + +- // host2 is 50 secs in slow start, the weight is scaled with time factor 40 / 60 == 0.66. ++ // host2 is 50 secs in slow start, the weight is scaled with time factor max(40/60, 0.1) = 0.66. + simTime().advanceTimeWait(std::chrono::seconds(30)); + + // Recalculate weights. +@@ -2265,22 +2388,35 @@ TEST_P(LeastRequestLoadBalancerTest, SlowStartWaitForPassingHC) { + hostSet().runCallbacks({}, {}); + + // We expect 11:2 ratio, as host2 is in slow start mode, its weight is scaled with factor +- // pow(0.1, 1.11)=0.07. Host1 is 7 seconds in slow start and its weight is scaled with active +- // request and time bias 0.53 * pow(0.7, 1.11) = 0.36. +- +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +- EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); ++ // max(pow(0.1, 1.11), 0.1)=0.1. Host1 is 7 seconds in slow start and its weight is scaled with ++ // active request and time bias 0.53 * max(pow(0.7, 1.11), 0.1) = 0.36. ++ ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[25/9, 10] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[50/9, 10] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[75/9, 10] ++ EXPECT_EQ(hostSet().healthy_hosts_[1], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[100/9, 10] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[100/9, 20] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[125/9, 20] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[150/9, 20] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[175/9, 20] ++ EXPECT_EQ(hostSet().healthy_hosts_[1], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[200/9, 20] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[200/9, 30] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[225/9, 30] ++ EXPECT_EQ(hostSet().healthy_hosts_[0], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[250/9, 30] ++ EXPECT_EQ(hostSet().healthy_hosts_[1], ++ lb_2.chooseHost(nullptr)); // before choose: edf.deadline[host1,host2]=[275/9, 30] + + simTime().advanceTimeWait(std::chrono::seconds(3)); + host1->healthFlagSet(Host::HealthFlag::FAILED_ACTIVE_HC); +@@ -2288,7 +2424,7 @@ TEST_P(LeastRequestLoadBalancerTest, SlowStartWaitForPassingHC) { + hostSet().runCallbacks({}, {}); + + // We expect 3:5 ratio, as host2 is 4 seconds in slow start, its weight is scaled with factor +- // pow(0.4, 1.11)=0.36. Host1 is not in slow start and its weight is scaled with active ++ // max(pow(0.4, 1.11), 0.1)=0.36. Host1 is not in slow start and its weight is scaled with active + // request bias = 0.53. + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); +@@ -2299,13 +2435,13 @@ TEST_P(LeastRequestLoadBalancerTest, SlowStartWaitForPassingHC) { + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + +- // Host2 is 7 seconds in slow start, the weight is scaled with time factor 7 / 10 == 0.6. ++ // Host2 is 7 seconds in slow start, the weight is scaled with time factor 7 / 10 == 0.7. + simTime().advanceTimeWait(std::chrono::seconds(3)); + + hostSet().runCallbacks({}, {}); + + // We expect 6:5 ratio, as host2 is in slow start mode, its weight is scaled with time factor +- // pow(0.7, 1.11)=0.67. Host1 weight is scaled with active request bias = 0.53. ++ // max(pow(0.7, 1.11), 0.1)=0.67. Host1 weight is scaled with active request bias = 0.53. + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); +diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc +index 79efee3c96..105063f071 100644 +--- a/test/common/upstream/upstream_impl_test.cc ++++ b/test/common/upstream/upstream_impl_test.cc +@@ -1793,6 +1793,90 @@ TEST_F(StaticClusterImplTest, RingHash) { + EXPECT_TRUE(cluster.info()->addedViaApi()); + } + ++TEST_F(StaticClusterImplTest, RoundRobinWithSlowStart) { ++ const std::string yaml = R"EOF( ++ name: staticcluster ++ connect_timeout: 0.25s ++ type: static ++ lb_policy: ROUND_ROBIN ++ load_assignment: ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: 10.0.0.1 ++ port_value: 11001 ++ round_robin_lb_config: ++ slow_start_config: ++ slow_start_window: 60s ++ aggression: ++ default_value: 2.0 ++ runtime_key: a_key ++ )EOF"; ++ ++ envoy::config::cluster::v3::Cluster cluster_config = parseClusterFromV3Yaml(yaml); ++ ++ Envoy::Stats::ScopePtr scope = stats_.createScope(fmt::format( ++ "cluster.{}.", cluster_config.alt_stat_name().empty() ? cluster_config.name() ++ : cluster_config.alt_stat_name())); ++ Envoy::Server::Configuration::TransportSocketFactoryContextImpl factory_context( ++ admin_, ssl_context_manager_, *scope, cm_, local_info_, dispatcher_, stats_, ++ singleton_manager_, tls_, validation_visitor_, *api_, options_); ++ StaticClusterImpl cluster(cluster_config, runtime_, factory_context, std::move(scope), true); ++ cluster.initialize([] {}); ++ ++ EXPECT_EQ(LoadBalancerType::RoundRobin, cluster.info()->lbType()); ++ auto slow_start_config = cluster.info()->lbRoundRobinConfig()->slow_start_config(); ++ EXPECT_EQ(std::chrono::milliseconds(60000), ++ std::chrono::milliseconds( ++ DurationUtil::durationToMilliseconds(slow_start_config.slow_start_window()))); ++ EXPECT_EQ(2.0, slow_start_config.aggression().default_value()); ++ EXPECT_TRUE(cluster.info()->addedViaApi()); ++} ++ ++TEST_F(StaticClusterImplTest, LeastRequestWithSlowStart) { ++ const std::string yaml = R"EOF( ++ name: staticcluster ++ connect_timeout: 0.25s ++ type: static ++ lb_policy: least_request ++ load_assignment: ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: 10.0.0.1 ++ port_value: 11001 ++ least_request_lb_config: ++ slow_start_config: ++ slow_start_window: 60s ++ aggression: ++ default_value: 2.0 ++ runtime_key: a_key ++ )EOF"; ++ ++ envoy::config::cluster::v3::Cluster cluster_config = parseClusterFromV3Yaml(yaml); ++ ++ Envoy::Stats::ScopePtr scope = stats_.createScope(fmt::format( ++ "cluster.{}.", cluster_config.alt_stat_name().empty() ? cluster_config.name() ++ : cluster_config.alt_stat_name())); ++ Envoy::Server::Configuration::TransportSocketFactoryContextImpl factory_context( ++ admin_, ssl_context_manager_, *scope, cm_, local_info_, dispatcher_, stats_, ++ singleton_manager_, tls_, validation_visitor_, *api_, options_); ++ StaticClusterImpl cluster(cluster_config, runtime_, factory_context, std::move(scope), true); ++ cluster.initialize([] {}); ++ ++ EXPECT_EQ(LoadBalancerType::LeastRequest, cluster.info()->lbType()); ++ auto slow_start_config = cluster.info()->lbLeastRequestConfig()->slow_start_config(); ++ EXPECT_EQ(std::chrono::milliseconds(60000), ++ std::chrono::milliseconds( ++ DurationUtil::durationToMilliseconds(slow_start_config.slow_start_window()))); ++ EXPECT_EQ(2.0, slow_start_config.aggression().default_value()); ++ EXPECT_TRUE(cluster.info()->addedViaApi()); ++} ++ + TEST_F(StaticClusterImplTest, OutlierDetector) { + const std::string yaml = R"EOF( + name: addressportconfig +diff --git a/test/config/utility.cc b/test/config/utility.cc +index a2d7c9df51..4158af993c 100644 +--- a/test/config/utility.cc ++++ b/test/config/utility.cc +@@ -432,6 +432,34 @@ envoy::config::cluster::v3::Cluster ConfigHelper::buildStaticCluster(const std:: + name, name, address, port, lb_policy)); + } + ++envoy::config::cluster::v3::Cluster ConfigHelper::buildH1ClusterWithHighCircuitBreakersLimits( ++ const std::string& name, int port, const std::string& address, const std::string& lb_policy) { ++ return TestUtility::parseYaml( ++ fmt::format(R"EOF( ++ name: {} ++ connect_timeout: 50s ++ type: STATIC ++ circuit_breakers: ++ thresholds: ++ - priority: DEFAULT ++ max_connections: 10000 ++ max_pending_requests: 10000 ++ max_requests: 10000 ++ max_retries: 10000 ++ load_assignment: ++ cluster_name: {} ++ endpoints: ++ - lb_endpoints: ++ - endpoint: ++ address: ++ socket_address: ++ address: {} ++ port_value: {} ++ lb_policy: {} ++ )EOF", ++ name, name, address, port, lb_policy)); ++} ++ + envoy::config::cluster::v3::Cluster ConfigHelper::buildCluster(const std::string& name, + const std::string& lb_policy) { + API_NO_BOOST(envoy::config::cluster::v3::Cluster) cluster; +diff --git a/test/config/utility.h b/test/config/utility.h +index f188f8ea1b..6c62292349 100644 +--- a/test/config/utility.h ++++ b/test/config/utility.h +@@ -150,6 +150,11 @@ public: + buildStaticCluster(const std::string& name, int port, const std::string& address, + const std::string& lb_policy = "ROUND_ROBIN"); + ++ static envoy::config::cluster::v3::Cluster ++ buildH1ClusterWithHighCircuitBreakersLimits(const std::string& name, int port, ++ const std::string& address, ++ const std::string& lb_policy = "ROUND_ROBIN"); ++ + // ADS configurations + static envoy::config::cluster::v3::Cluster + buildCluster(const std::string& name, const std::string& lb_policy = "ROUND_ROBIN"); +diff --git a/test/config_test/BUILD b/test/config_test/BUILD +index 7104a8d336..a04ed9a83e 100644 +--- a/test/config_test/BUILD ++++ b/test/config_test/BUILD +@@ -5,7 +5,7 @@ load( + "envoy_package", + ) + load("//source/extensions:all_extensions.bzl", "envoy_all_extensions") +-load("//bazel:repositories.bzl", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") ++load("//bazel:repositories.bzl", "DARWIN_SKIP_TARGETS", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") + + licenses(["notice"]) # Apache 2 + +@@ -60,6 +60,7 @@ envoy_cc_test_library( + ] + select({ + "//bazel:windows_x86_64": envoy_all_extensions(WINDOWS_SKIP_TARGETS), + "//bazel:linux_ppc": envoy_all_extensions(PPC_SKIP_TARGETS), ++ "//bazel:darwin": envoy_all_extensions(DARWIN_SKIP_TARGETS), + "//conditions:default": envoy_all_extensions(), + }), + ) +diff --git a/test/config_test/config_test.cc b/test/config_test/config_test.cc +index d6f8d800f9..bd441e6a75 100644 +--- a/test/config_test/config_test.cc ++++ b/test/config_test/config_test.cc +@@ -47,7 +47,7 @@ OptionsImpl asConfigYaml(const OptionsImpl& src, Api::Api& api) { + + static std::vector unsuported_win32_configs = { + #if defined(WIN32) && !defined(SO_ORIGINAL_DST) +- "configs_original-dst-cluster_proxy_config.yaml" ++ "configs_original-dst-cluster_proxy_config.yaml", + #endif + }; + +diff --git a/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc b/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc +index 27a9a70b45..67461b23f4 100644 +--- a/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc ++++ b/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc +@@ -328,6 +328,82 @@ TEST_F(ExtAuthzHttpClientTest, AllowedRequestHeadersPrefix) { + EXPECT_EQ(fool[0]->value().getStringView(), "fool"); + } + ++#if defined(ALIMESH) ++TEST_F(ExtAuthzHttpClientTest, IsAuthorizationPass) { ++ // 200 code without x-mse-external-authz-check-result ++ const auto expected_headers = TestCommon::makeHeaderValueOption({{":status", "200", false}}); ++ auto check_response = TestCommon::makeMessageResponse(expected_headers); ++ EXPECT_TRUE(isAuthorizationPass(check_response->headers())); ++ ++ // 200 code with x-mse-external-authz-check-result value is true ++ expected_headers = TestCommon::makeHeaderValueOption( ++ {{":status", "200", false}, {"x-mse-external-authz-check-result", "true", false}}); ++ check_response = TestCommon::makeMessageResponse(expected_headers); ++ EXPECT_TRUE(isAuthorizationPass(check_response->headers())); ++ ++ // 200 code with x-mse-external-authz-check-result value is false ++ expected_headers = TestCommon::makeHeaderValueOption( ++ {{":status", "200", false}, {"x-mse-external-authz-check-result", "false", false}}); ++ check_response = TestCommon::makeMessageResponse(expected_headers); ++ EXPECT_FALSE(isAuthorizationPass(check_response->headers())); ++ ++ // nor 200 code with x-mse-external-authz-check-result value is true ++ expected_headers = TestCommon::makeHeaderValueOption( ++ {{":status", "503", false}, {"x-mse-external-authz-check-result", "true", false}}); ++ check_response = TestCommon::makeMessageResponse(expected_headers); ++ EXPECT_FALSE(isAuthorizationPass(check_response->headers())); ++} ++ ++TEST_F(ExtAuthzHttpClientTest, AuthorizationOkWithXMseExternalAuthzCheckResultTrue) { ++ const auto expected_headers = TestCommon::makeHeaderValueOption( ++ {{":status", "200", false}, {"x-mse-external-authz-check-result", "true", false}}); ++ const auto authz_response = TestCommon::makeAuthzResponse(CheckStatus::OK); ++ auto check_response = TestCommon::makeMessageResponse(expected_headers); ++ envoy::service::auth::v3::CheckRequest request; ++ client_->check(request_callbacks_, request, parent_span_, stream_info_); ++ ++ EXPECT_CALL(request_callbacks_, ++ onComplete_(WhenDynamicCastTo(AuthzOkResponse(authz_response)))); ++ client_->onSuccess(async_request_, std::move(check_response)); ++} ++ ++TEST_F(ExtAuthzHttpClientTest, AuthorizationDeniedWithXMseExternalAuthzCheckResultTrueButCode403) { ++ const auto expected_headers = TestCommon::makeHeaderValueOption( ++ {{":status", "403", false}, {"x-mse-external-authz-check-result", "true", false}}); ++ const auto authz_response = TestCommon::makeAuthzResponse( ++ CheckStatus::Denied, Http::Code::Forbidden, EMPTY_STRING, expected_headers); ++ auto check_response = TestCommon::makeMessageResponse(expected_headers); ++ ++ envoy::service::auth::v3::CheckRequest request; ++ client_->check(request_callbacks_, request, parent_span_, stream_info_); ++ ++ // Check for child span tagging when the request is denied. ++ EXPECT_CALL(child_span_, setTag(Eq("ext_authz_http_status"), Eq("Forbidden"))); ++ EXPECT_CALL(child_span_, setTag(Eq("ext_authz_status"), Eq("ext_authz_unauthorized"))); ++ client_->onBeforeFinalizeUpstreamSpan(child_span_, &check_response->headers()); ++ ++ EXPECT_CALL(request_callbacks_, ++ onComplete_(WhenDynamicCastTo(AuthzDeniedResponse(authz_response)))); ++ client_->onSuccess(async_request_, TestCommon::makeMessageResponse(expected_headers)); ++} ++ ++TEST_F(ExtAuthzHttpClientTest, AuthorizationDeniedWithCode200ButXMseExternalAuthzCheckResultFalse) { ++ const auto expected_body = std::string{"test"}; ++ const auto expected_headers = TestCommon::makeHeaderValueOption( ++ {{":status", "200", false}, {"x-mse-external-authz-check-result", "false", false}}); ++ const auto authz_response = TestCommon::makeAuthzResponse(CheckStatus::Denied, Http::Code::OK, ++ expected_body, expected_headers); ++ ++ envoy::service::auth::v3::CheckRequest request; ++ client_->check(request_callbacks_, request, parent_span_, stream_info_); ++ ++ EXPECT_CALL(request_callbacks_, ++ onComplete_(WhenDynamicCastTo(AuthzDeniedResponse(authz_response)))); ++ client_->onSuccess(async_request_, ++ TestCommon::makeMessageResponse(expected_headers, expected_body)); ++} ++#endif ++ + // Verify client response when authorization server returns a 200 OK. + TEST_F(ExtAuthzHttpClientTest, AuthorizationOk) { + const auto expected_headers = TestCommon::makeHeaderValueOption({{":status", "200", false}}); +diff --git a/test/extensions/filters/http/cors/cors_filter_integration_test.cc b/test/extensions/filters/http/cors/cors_filter_integration_test.cc +index 00bd075b37..7ccd82561b 100644 +--- a/test/extensions/filters/http/cors/cors_filter_integration_test.cc ++++ b/test/extensions/filters/http/cors/cors_filter_integration_test.cc +@@ -114,6 +114,12 @@ protected: + Http::TestResponseHeaderMapImpl& expected_response_headers) { + response_headers.remove(Envoy::Http::LowerCaseString{"date"}); + response_headers.remove(Envoy::Http::LowerCaseString{"x-envoy-upstream-service-time"}); ++#if defined(ALIMESH) ++ response_headers.remove(Envoy::Http::LowerCaseString{"req-cost-time"}); ++ response_headers.remove(Envoy::Http::LowerCaseString{"req-start-time"}); ++ response_headers.remove(Envoy::Http::LowerCaseString{"req-arrive-time"}); ++ response_headers.remove(Envoy::Http::LowerCaseString{"resp-start-time"}); ++#endif + EXPECT_EQ(expected_response_headers, response_headers); + } + }; +diff --git a/test/extensions/filters/http/cors/cors_filter_test.cc b/test/extensions/filters/http/cors/cors_filter_test.cc +index 31c7f211cd..8bec16d049 100644 +--- a/test/extensions/filters/http/cors/cors_filter_test.cc ++++ b/test/extensions/filters/http/cors/cors_filter_test.cc +@@ -716,6 +716,61 @@ TEST(CorsFilterConfigTest, DEPRECATED_FEATURE_TEST(DeprecatedExtensionFilterName + deprecated_name)); + } + ++TEST_F(CorsFilterTest, OptionsRequestWithWildcardAllowMethods) { ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "OPTIONS"}, ++ {"origin", "www.envoyproxy.com"}, ++ {"access-control-request-method", "GET"}}; ++ ++ Http::TestResponseHeaderMapImpl response_headers{ ++ {":status", "200"}, ++ {"access-control-allow-origin", "www.envoyproxy.com"}, ++ {"access-control-allow-methods", "GET"}, ++ {"access-control-allow-headers", "content-type"}, ++ {"access-control-max-age", "0"}, ++ }; ++ ++ cors_policy_->allow_methods_ = "*"; ++ ++ EXPECT_CALL(decoder_callbacks_, encodeHeaders_(HeaderMapEqualRef(&response_headers), true)); ++ ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_.decodeHeaders(request_headers, false)); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data_, false)); ++ EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(request_trailers_)); ++ ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.encodeHeaders(response_headers_, false)); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.encodeData(data_, false)); ++ EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.encodeTrailers(response_trailers_)); ++} ++ ++TEST_F(CorsFilterTest, OptionsRequestWithWildcardAllowHeaders) { ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "OPTIONS"}, ++ {"origin", "www.envoyproxy.com"}, ++ {"access-control-request-method", "GET"}, ++ {"access-control-request-headers", "test,pre"}}; ++ ++ Http::TestResponseHeaderMapImpl response_headers{ ++ {":status", "200"}, ++ {"access-control-allow-origin", "www.envoyproxy.com"}, ++ {"access-control-allow-methods", "GET"}, ++ {"access-control-allow-headers", "test,pre"}, ++ {"access-control-max-age", "0"}, ++ }; ++ ++ cors_policy_->allow_headers_ = "*"; ++ ++ EXPECT_CALL(decoder_callbacks_, encodeHeaders_(HeaderMapEqualRef(&response_headers), true)); ++ ++ EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, ++ filter_.decodeHeaders(request_headers, false)); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data_, false)); ++ EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(request_trailers_)); ++ ++ EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.encodeHeaders(response_headers_, false)); ++ EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.encodeData(data_, false)); ++ EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.encodeTrailers(response_trailers_)); ++} ++ + } // namespace Cors + } // namespace HttpFilters + } // namespace Extensions +diff --git a/test/extensions/filters/http/tap/tap_filter_integration_test.cc b/test/extensions/filters/http/tap/tap_filter_integration_test.cc +index cfd7f76445..ba4263f7d1 100644 +--- a/test/extensions/filters/http/tap/tap_filter_integration_test.cc ++++ b/test/extensions/filters/http/tap/tap_filter_integration_test.cc +@@ -272,8 +272,13 @@ tap_config: + admin_response_->waitForBodyData(1); + envoy::data::tap::v3::TraceWrapper trace; + TestUtility::loadFromYaml(admin_response_->body(), trace); ++#if defined(ALIMESH) ++ EXPECT_EQ(trace.http_buffered_trace().request().headers().size(), 10); ++ EXPECT_EQ(trace.http_buffered_trace().response().headers().size(), 7); ++#else + EXPECT_EQ(trace.http_buffered_trace().request().headers().size(), 8); + EXPECT_EQ(trace.http_buffered_trace().response().headers().size(), 4); ++#endif + admin_response_->clearBody(); + + // Do a request which should not tap. +@@ -285,11 +290,16 @@ tap_config: + // Wait for the tap message. + admin_response_->waitForBodyData(1); + TestUtility::loadFromYaml(admin_response_->body(), trace); ++#if defined(ALIMESH) ++ EXPECT_EQ(trace.http_buffered_trace().request().headers().size(), 9); ++ EXPECT_EQ(trace.http_buffered_trace().response().headers().size(), 8); ++#else + EXPECT_EQ(trace.http_buffered_trace().request().headers().size(), 7); ++ EXPECT_EQ(trace.http_buffered_trace().response().headers().size(), 5); ++#endif + EXPECT_EQ( + "http", + findHeader("x-forwarded-proto", trace.http_buffered_trace().request().headers())->value()); +- EXPECT_EQ(trace.http_buffered_trace().response().headers().size(), 5); + EXPECT_NE(nullptr, findHeader("date", trace.http_buffered_trace().response().headers())); + EXPECT_EQ("baz", findHeader("bar", trace.http_buffered_trace().response().headers())->value()); + +diff --git a/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc b/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc +index 9d3d89fb26..be500599a4 100644 +--- a/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc ++++ b/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc +@@ -68,8 +68,9 @@ protected: + NiceMock* timer_; + Event::TimerCb timer_cb_; + std::string test_string = "ABCDEFGHIJKLMN"; +- SkyWalkingTracerStats tracing_stats_{ +- SKYWALKING_TRACER_STATS(POOL_COUNTER_PREFIX(mock_scope_, "tracing.skywalking."))}; ++ SkyWalkingTracerStatsSharedPtr tracing_stats_{ ++ std::make_shared(SkyWalkingTracerStats{ ++ SKYWALKING_TRACER_STATS(POOL_COUNTER_PREFIX(mock_scope_, "tracing.skywalking."))})}; + TraceSegmentReporterPtr reporter_; + }; + +diff --git a/test/extensions/tracers/skywalking/tracer_test.cc b/test/extensions/tracers/skywalking/tracer_test.cc +index 014aa4b150..0d2298c3af 100644 +--- a/test/extensions/tracers/skywalking/tracer_test.cc ++++ b/test/extensions/tracers/skywalking/tracer_test.cc +@@ -64,8 +64,9 @@ protected: + NiceMock& mock_scope_ = context_.server_factory_context_.scope_; + std::unique_ptr> mock_stream_ptr_{nullptr}; + std::string test_string = "ABCDEFGHIJKLMN"; +- SkyWalkingTracerStats tracing_stats_{ +- SKYWALKING_TRACER_STATS(POOL_COUNTER_PREFIX(mock_scope_, "tracing.skywalking."))}; ++ SkyWalkingTracerStatsSharedPtr tracing_stats_{ ++ std::make_shared(SkyWalkingTracerStats{ ++ SKYWALKING_TRACER_STATS(POOL_COUNTER_PREFIX(mock_scope_, "tracing.skywalking."))})}; + TracerPtr tracer_; + }; + +diff --git a/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_test.cc b/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_test.cc +index 17c0fafd34..532b16fe0d 100644 +--- a/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_test.cc ++++ b/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_test.cc +@@ -388,7 +388,6 @@ TEST_F(ProxyProtocolTest, V2IPV4DownstreamAddresses) { + proxy_protocol_socket_->doWrite(msg, false); + } + +-// Test injects V2 PROXY protocol for downstream IPV6 addresses + TEST_F(ProxyProtocolTest, V2IPV6DownstreamAddresses) { + auto src_addr = + Network::Address::InstanceConstSharedPtr(new Network::Address::Ipv6Instance("1:2:3::4", 8)); +diff --git a/test/extensions/upstreams/http/tcp/upstream_request_test.cc b/test/extensions/upstreams/http/tcp/upstream_request_test.cc +index c5310d25fe..f9a1bcbdb1 100644 +--- a/test/extensions/upstreams/http/tcp/upstream_request_test.cc ++++ b/test/extensions/upstreams/http/tcp/upstream_request_test.cc +@@ -146,7 +146,7 @@ TEST_F(TcpUpstreamTest, Basic) { + + TEST_F(TcpUpstreamTest, V1Header) { + envoy::config::core::v3::ProxyProtocolConfig* proxy_config = +- mock_router_filter_.route_entry_.connect_config_->mutable_proxy_protocol_config(); ++ mock_router_filter_.route_.route_entry_.connect_config_->mutable_proxy_protocol_config(); + proxy_config->set_version(envoy::config::core::v3::ProxyProtocolConfig::V1); + mock_router_filter_.client_connection_.stream_info_.downstream_connection_info_provider_ + ->setRemoteAddress(std::make_shared("1.2.3.4", 5)); +@@ -169,7 +169,7 @@ TEST_F(TcpUpstreamTest, V1Header) { + + TEST_F(TcpUpstreamTest, V2Header) { + envoy::config::core::v3::ProxyProtocolConfig* proxy_config = +- mock_router_filter_.route_entry_.connect_config_->mutable_proxy_protocol_config(); ++ mock_router_filter_.route_.route_entry_.connect_config_->mutable_proxy_protocol_config(); + proxy_config->set_version(envoy::config::core::v3::ProxyProtocolConfig::V2); + mock_router_filter_.client_connection_.stream_info_.downstream_connection_info_provider_ + ->setRemoteAddress(std::make_shared("1.2.3.4", 5)); +diff --git a/test/integration/BUILD b/test/integration/BUILD +index 5e631735ef..8f0d1cf58c 100644 +--- a/test/integration/BUILD ++++ b/test/integration/BUILD +@@ -111,10 +111,12 @@ envoy_proto_library( + + envoy_cc_test( + name = "cds_integration_test", ++ size = "large", + srcs = ["cds_integration_test.cc"], + data = [ + "//test/config/integration/certs", + ], ++ shard_count = 4, + deps = [ + ":http_integration_lib", + "//source/common/config:protobuf_link_hacks", +@@ -509,6 +511,7 @@ envoy_cc_test_library( + "//source/extensions/filters/http/buffer:config", + "//source/extensions/filters/http/health_check:config", + "//test/common/http/http2:http2_frame", ++ "//test/integration/filters:buffer_continue_filter_lib", + "//test/integration/filters:continue_after_local_reply_filter_lib", + "//test/integration/filters:continue_headers_only_inject_body", + "//test/integration/filters:encoder_decoder_buffer_filter_lib", +diff --git a/test/integration/cds_integration_test.cc b/test/integration/cds_integration_test.cc +index bbffa27e95..f7e2b27843 100644 +--- a/test/integration/cds_integration_test.cc ++++ b/test/integration/cds_integration_test.cc +@@ -34,7 +34,15 @@ public: + CdsIntegrationTest() + : HttpIntegrationTest(Http::CodecType::HTTP2, ipVersion(), + ConfigHelper::discoveredClustersBootstrap( +- sotwOrDelta() == Grpc::SotwOrDelta::Sotw ? "GRPC" : "DELTA_GRPC")) { ++ sotwOrDelta() == Grpc::SotwOrDelta::Sotw || ++ sotwOrDelta() == Grpc::SotwOrDelta::UnifiedSotw ++ ? "GRPC" ++ : "DELTA_GRPC")), ++ cluster_creator_(&ConfigHelper::buildStaticCluster) { ++ if (sotwOrDelta() == Grpc::SotwOrDelta::UnifiedSotw || ++ sotwOrDelta() == Grpc::SotwOrDelta::UnifiedDelta) { ++ config_helper_.addRuntimeOverride("envoy.reloadable_features.unified_mux", "true"); ++ } + use_lds_ = false; + sotw_or_delta_ = sotwOrDelta(); + } +@@ -72,14 +80,14 @@ public: + // Create the regular (i.e. not an xDS server) upstreams. We create them manually here after + // initialize() because finalize() expects all fake_upstreams_ to correspond to a static + // cluster in the bootstrap config - which we don't want since we're testing dynamic CDS! +- addFakeUpstream(Http::CodecType::HTTP2); +- addFakeUpstream(Http::CodecType::HTTP2); +- cluster1_ = ConfigHelper::buildStaticCluster( ++ addFakeUpstream(upstream_codec_type_); ++ addFakeUpstream(upstream_codec_type_); ++ cluster1_ = cluster_creator_( + ClusterName1, fake_upstreams_[UpstreamIndex1]->localAddress()->ip()->port(), +- Network::Test::getLoopbackAddressString(ipVersion())); +- cluster2_ = ConfigHelper::buildStaticCluster( ++ Network::Test::getLoopbackAddressString(ipVersion()), "ROUND_ROBIN"); ++ cluster2_ = cluster_creator_( + ClusterName2, fake_upstreams_[UpstreamIndex2]->localAddress()->ip()->port(), +- Network::Test::getLoopbackAddressString(ipVersion())); ++ Network::Test::getLoopbackAddressString(ipVersion()), "ROUND_ROBIN"); + + // Let Envoy establish its connection to the CDS server. + acceptXdsConnection(); +@@ -126,6 +134,10 @@ public: + envoy::config::cluster::v3::Cluster cluster2_; + // True if we decided not to run the test after all. + bool test_skipped_{true}; ++ Http::CodecType upstream_codec_type_{Http::CodecType::HTTP2}; ++ std::function ++ cluster_creator_; + }; + + INSTANTIATE_TEST_SUITE_P(IpVersionsClientTypeDelta, CdsIntegrationTest, +@@ -301,5 +313,160 @@ TEST_P(CdsIntegrationTest, VersionsRememberedAfterReconnect) { + ASSERT_TRUE(codec_client_->waitForDisconnect()); + } + ++// This test verifies that Envoy can delete a cluster with a lot of idle connections. ++// The original problem was recursive closure of idle connections that can run out ++// of stack when there are a lot of idle connections. ++TEST_P(CdsIntegrationTest, CdsClusterDownWithLotsOfIdleConnections) { ++ constexpr int num_requests = 2000; ++ // Make upstream H/1 so it creates connection for each request ++ upstream_codec_type_ = Http::CodecType::HTTP1; ++ // Relax default circuit breaker limits and timeouts so Envoy can accumulate a lot of idle ++ // connections ++ cluster_creator_ = &ConfigHelper::buildH1ClusterWithHighCircuitBreakersLimits; ++ config_helper_.addConfigModifier( ++ [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& ++ hcm) -> void { ++ hcm.mutable_route_config() ++ ->mutable_virtual_hosts(0) ++ ->mutable_routes(0) ++ ->mutable_route() ++ ->mutable_timeout() ++ ->set_seconds(600); ++ hcm.mutable_route_config() ++ ->mutable_virtual_hosts(0) ++ ->mutable_routes(0) ++ ->mutable_route() ++ ->mutable_idle_timeout() ++ ->set_seconds(600); ++ }); ++ initialize(); ++ std::vector responses; ++ std::vector upstream_connections; ++ std::vector upstream_requests; ++ codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); ++ // The first loop establishes a lot of open connections with active requests to upstream ++ for (int i = 0; i < num_requests; ++i) { ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/cluster1"}, ++ {":scheme", "http"}, ++ {":authority", "host"}, ++ {"x-lyft-user-id", absl::StrCat(i)}}; ++ ++ auto response = codec_client_->makeHeaderOnlyRequest(request_headers); ++ responses.push_back(std::move(response)); ++ ++ FakeHttpConnectionPtr fake_upstream_connection; ++ waitForNextUpstreamConnection({UpstreamIndex1}, TestUtility::DefaultTimeout, ++ fake_upstream_connection); ++ // Wait for the next stream on the upstream connection. ++ FakeStreamPtr upstream_request; ++ AssertionResult result = ++ fake_upstream_connection->waitForNewStream(*dispatcher_, upstream_request); ++ RELEASE_ASSERT(result, result.message()); ++ // Wait for the stream to be completely received. ++ result = upstream_request->waitForEndStream(*dispatcher_); ++ RELEASE_ASSERT(result, result.message()); ++ upstream_connections.push_back(std::move(fake_upstream_connection)); ++ upstream_requests.push_back(std::move(upstream_request)); ++ } ++ ++ // This loop completes all requests making the all upstream connections idle ++ for (int i = 0; i < num_requests; ++i) { ++ // Send response headers, and end_stream if there is no response body. ++ upstream_requests[i]->encodeHeaders(default_response_headers_, true); ++ // Wait for the response to be read by the codec client. ++ RELEASE_ASSERT(responses[i]->waitForEndStream(), "unexpected timeout"); ++ ASSERT_TRUE(responses[i]->complete()); ++ EXPECT_EQ("200", responses[i]->headers().getStatusValue()); ++ } ++ ++ test_server_->waitForCounterGe("cluster_manager.cluster_added", 1); ++ ++ // Tell Envoy that cluster_1 is gone. Envoy will try to close all idle connections ++ EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().Cluster, "55", {}, {}, {})); ++ sendDiscoveryResponse(Config::TypeUrl::get().Cluster, {}, {}, ++ {ClusterName1}, "42"); ++ // We can continue the test once we're sure that Envoy's ClusterManager has made use of ++ // the DiscoveryResponse that says cluster_1 is gone. ++ test_server_->waitForCounterGe("cluster_manager.cluster_removed", 1); ++ ++ // If we made it this far then everything is ok. ++ for (int i = 0; i < num_requests; ++i) { ++ AssertionResult result = upstream_connections[i]->close(); ++ RELEASE_ASSERT(result, result.message()); ++ result = upstream_connections[i]->waitForDisconnect(); ++ RELEASE_ASSERT(result, result.message()); ++ } ++ upstream_connections.clear(); ++ cleanupUpstreamAndDownstream(); ++ ASSERT_TRUE(codec_client_->waitForDisconnect()); ++} ++ ++// This test verifies that Envoy can delete a cluster with a lot of connections in the connecting ++// state and associated pending requests. The recursion guard in the ++// ConnPoolImplBase::closeIdleConnectionsForDrainingPool() would fire if it was called recursively. ++// ++// Test is currently disabled as there is presently no reliable way of making upstream connections ++// hang in connecting state. ++TEST_P(CdsIntegrationTest, DISABLED_CdsClusterDownWithLotsOfConnectingConnections) { ++ // Use low number of pending connections to prevent bumping into the default ++ // limit of 128, since the upstream will be prevented below from ++ // accepting connections. ++ constexpr int num_requests = 64; ++ // Make upstream H/1 so it creates connection for each request ++ upstream_codec_type_ = Http::CodecType::HTTP1; ++ cluster_creator_ = &ConfigHelper::buildH1ClusterWithHighCircuitBreakersLimits; ++ config_helper_.addConfigModifier( ++ [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& ++ hcm) -> void { ++ hcm.mutable_route_config() ++ ->mutable_virtual_hosts(0) ++ ->mutable_routes(0) ++ ->mutable_route() ++ ->mutable_timeout() ++ ->set_seconds(600); ++ hcm.mutable_route_config() ++ ->mutable_virtual_hosts(0) ++ ->mutable_routes(0) ++ ->mutable_route() ++ ->mutable_idle_timeout() ++ ->set_seconds(600); ++ }); ++ initialize(); ++ test_server_->waitForCounterGe("cluster_manager.cluster_added", 1); ++ std::vector responses; ++ codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); ++ // Stop upstream at UpstreamIndex1 dispatcher, to prevent it from accepting TCP connections. ++ // This will cause Envoy's connections to that upstream hang in the connecting state. ++ fake_upstreams_[UpstreamIndex1]->dispatcher()->exit(); ++ for (int i = 0; i < num_requests; ++i) { ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, ++ {":path", "/cluster1"}, ++ {":scheme", "http"}, ++ {":authority", "host"}, ++ {"x-lyft-user-id", absl::StrCat(i)}}; ++ ++ auto response = codec_client_->makeHeaderOnlyRequest(request_headers); ++ responses.push_back(std::move(response)); ++ } ++ ++ // Wait for Envoy to try to establish all expected connections ++ test_server_->waitForCounterEq("cluster.cluster_1.upstream_cx_total", num_requests); ++ ++ // Tell Envoy that cluster_1 is gone. Envoy will try to close all pending connections ++ EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().Cluster, "55", {}, {}, {})); ++ sendDiscoveryResponse(Config::TypeUrl::get().Cluster, {}, {}, ++ {ClusterName1}, "42"); ++ // We can continue the test once we're sure that Envoy's ClusterManager has made use of ++ // the DiscoveryResponse that says cluster_1 is gone. ++ test_server_->waitForCounterGe("cluster_manager.cluster_removed", 1); ++ ++ cleanupUpstreamAndDownstream(); ++ ASSERT_TRUE(codec_client_->waitForDisconnect()); ++ // If we got here it means that the recursion guard in the ++ // ConnPoolImplBase::closeIdleConnectionsForDrainingPool() did not fire, which is what this test ++ // validates. ++} ++ + } // namespace + } // namespace Envoy +diff --git a/test/integration/extension_discovery_integration_test.cc b/test/integration/extension_discovery_integration_test.cc +index 7a6457027f..f279a5e3d4 100644 +--- a/test/integration/extension_discovery_integration_test.cc ++++ b/test/integration/extension_discovery_integration_test.cc +@@ -733,5 +733,60 @@ TEST_P(ExtensionDiscoveryIntegrationTest, BasicFailTerminalFilterNotAtEndOfFilte + EXPECT_EQ("500", response->headers().getStatusValue()); + } + ++// Validate that deleting listeners does not break active ECDS subscription. ++TEST_P(ExtensionDiscoveryIntegrationTest, ReloadBoth) { ++ on_server_init_function_ = [&]() { waitXdsStream(); }; ++ addDynamicFilter("foo", false); ++ initialize(); ++ test_server_->waitForCounterGe("listener_manager.lds.update_success", 1); ++ EXPECT_EQ(test_server_->server().initManager().state(), Init::Manager::State::Initializing); ++ registerTestServerPorts({"http"}); ++ sendXdsResponse("foo", "1", denyPrivateConfig()); ++ test_server_->waitForCounterGe("http.config_test.extension_config_discovery.foo.config_reload", ++ 1); ++ test_server_->waitUntilListenersReady(); ++ test_server_->waitForGaugeGe("listener_manager.workers_started", 1); ++ EXPECT_EQ(test_server_->server().initManager().state(), Init::Manager::State::Initialized); ++ Http::TestRequestHeaderMapImpl banned_request_headers{ ++ {":method", "GET"}, {":path", "/private/key"}, {":scheme", "http"}, {":authority", "host"}}; ++ codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); ++ { ++ auto response = codec_client_->makeHeaderOnlyRequest(banned_request_headers); ++ ASSERT_TRUE(response->waitForEndStream()); ++ ASSERT_TRUE(response->complete()); ++ EXPECT_EQ("403", response->headers().getStatusValue()); ++ } ++ codec_client_->close(); ++ ++ // Rename the listener to force delete the first listener and wait for the deletion. ++ listener_config_.set_name("updated"); ++ sendLdsResponse("updated"); ++ test_server_->waitForCounterGe("listener_manager.lds.update_success", 2); ++ test_server_->waitForGaugeEq("listener_manager.total_listeners_warming", 0); ++ test_server_->waitForGaugeEq("listener_manager.total_listeners_draining", 0); ++ ++ // Verify ECDS is still applied on the new listener. ++ registerTestServerPorts({"http"}); ++ codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); ++ { ++ auto response = codec_client_->makeHeaderOnlyRequest(banned_request_headers); ++ ASSERT_TRUE(response->waitForEndStream()); ++ ASSERT_TRUE(response->complete()); ++ EXPECT_EQ("403", response->headers().getStatusValue()); ++ } ++ ++ // Update ECDS but keep the connection. ++ { ++ sendXdsResponse("foo", "2", allowAllConfig()); ++ test_server_->waitForCounterGe("http.config_test.extension_config_discovery.foo.config_reload", ++ 2); ++ auto response = codec_client_->makeHeaderOnlyRequest(banned_request_headers); ++ ASSERT_TRUE(response->waitForEndStream()); ++ ASSERT_TRUE(response->complete()); ++ EXPECT_EQ("200", response->headers().getStatusValue()); ++ } ++ codec_client_->close(); ++} ++ + } // namespace + } // namespace Envoy +diff --git a/test/integration/filter_manager_integration_test.cc b/test/integration/filter_manager_integration_test.cc +index ee5db8d467..7a160aa2e8 100644 +--- a/test/integration/filter_manager_integration_test.cc ++++ b/test/integration/filter_manager_integration_test.cc +@@ -458,6 +458,7 @@ TEST_P(InjectDataWithEchoFilterIntegrationTest, UsageOfInjectDataMethodsShouldBe + } + + TEST_P(InjectDataWithEchoFilterIntegrationTest, FilterChainMismatch) { ++ useListenerAccessLog("%RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS%"); + useListenerAccessLog("%FILTER_CHAIN_NAME% %RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS%"); + config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + bootstrap.mutable_static_resources() +diff --git a/test/integration/filters/BUILD b/test/integration/filters/BUILD +index 79e08f2533..beab9eccde 100644 +--- a/test/integration/filters/BUILD ++++ b/test/integration/filters/BUILD +@@ -514,6 +514,20 @@ envoy_cc_test_library( + ], + ) + ++envoy_cc_test_library( ++ name = "buffer_continue_filter_lib", ++ srcs = [ ++ "buffer_continue_filter.cc", ++ ], ++ deps = [ ++ "//envoy/http:filter_interface", ++ "//envoy/registry", ++ "//envoy/server:filter_config_interface", ++ "//source/extensions/filters/http/common:pass_through_filter_lib", ++ "//test/extensions/filters/http/common:empty_http_filter_config_lib", ++ ], ++) ++ + envoy_cc_test_library( + name = "test_socket_interface_lib", + srcs = [ +diff --git a/test/integration/filters/buffer_continue_filter.cc b/test/integration/filters/buffer_continue_filter.cc +new file mode 100644 +index 0000000000..d5f5dadd69 +--- /dev/null ++++ b/test/integration/filters/buffer_continue_filter.cc +@@ -0,0 +1,74 @@ ++#include ++ ++#include "envoy/http/filter.h" ++#include "envoy/registry/registry.h" ++#include "envoy/server/filter_config.h" ++ ++#include "source/extensions/filters/http/common/pass_through_filter.h" ++ ++#include "test/extensions/filters/http/common/empty_http_filter_config.h" ++ ++namespace Envoy { ++ ++// A filter that buffers until the limit is reached and then continues. ++class BufferContinueStreamFilter : public Http::PassThroughFilter { ++public: ++ Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap&, bool end_stream) override { ++ return end_stream ? Http::FilterHeadersStatus::Continue ++ : Http::FilterHeadersStatus::StopIteration; ++ } ++ ++ Http::FilterDataStatus decodeData(Buffer::Instance&, bool end_stream) override { ++ return end_stream ? Http::FilterDataStatus::Continue ++ : Http::FilterDataStatus::StopIterationAndBuffer; ++ } ++ ++ Http::FilterHeadersStatus encodeHeaders(Http::ResponseHeaderMap& headers, bool) override { ++ response_headers_ = &headers; ++ return Http::FilterHeadersStatus::StopIteration; ++ } ++ ++ Http::FilterDataStatus encodeData(Buffer::Instance& data, bool end_stream) override { ++ data_total_ += data.length(); ++ ++ const auto limit = encoder_callbacks_->encoderBufferLimit(); ++ const auto header_size = response_headers_->byteSize(); ++ ++ if (limit && header_size + data_total_ > limit) { ++ // Give up since we've reached the buffer limit, Envoy should generate ++ // a 500 since it couldn't finished encoding. ++ return Http::FilterDataStatus::Continue; ++ } ++ ++ encoder_callbacks_->addEncodedData(data, false); ++ ++ if (!end_stream) { ++ return Http::FilterDataStatus::StopIterationAndBuffer; ++ } ++ ++ return Http::FilterDataStatus::Continue; ++ } ++ ++private: ++ Http::ResponseHeaderMap* response_headers_; ++ uint64_t data_total_{0}; ++}; ++ ++class BufferContinueFilterConfig : public Extensions::HttpFilters::Common::EmptyHttpFilterConfig { ++public: ++ BufferContinueFilterConfig() : EmptyHttpFilterConfig("buffer-continue-filter") {} ++ ++ Http::FilterFactoryCb createFilter(const std::string&, ++ Server::Configuration::FactoryContext&) override { ++ return [](Http::FilterChainFactoryCallbacks& callbacks) -> void { ++ callbacks.addStreamFilter(std::make_shared<::Envoy::BufferContinueStreamFilter>()); ++ }; ++ } ++}; ++ ++// perform static registration ++static Registry::RegisterFactory ++ register_; ++ ++} // namespace Envoy +diff --git a/test/integration/header_integration_test.cc b/test/integration/header_integration_test.cc +index 2ceef32088..436519450c 100644 +--- a/test/integration/header_integration_test.cc ++++ b/test/integration/header_integration_test.cc +@@ -437,6 +437,13 @@ protected: + void compareHeaders(Headers&& headers, const ExpectedHeaders& expected_headers) { + headers.remove(Envoy::Http::LowerCaseString{"content-length"}); + headers.remove(Envoy::Http::LowerCaseString{"date"}); ++#if defined(ALIMESH) ++ headers.remove(Envoy::Http::LowerCaseString{"req-start-time"}); ++ headers.remove(Envoy::Http::LowerCaseString{"req-cost-time"}); ++ headers.remove(Envoy::Http::LowerCaseString{"x-envoy-original-host"}); ++ headers.remove(Envoy::Http::LowerCaseString{"req-arrive-time"}); ++ headers.remove(Envoy::Http::LowerCaseString{"resp-start-time"}); ++#endif + if (!routerSuppressEnvoyHeaders()) { + headers.remove(Envoy::Http::LowerCaseString{"x-envoy-expected-rq-timeout-ms"}); + headers.remove(Envoy::Http::LowerCaseString{"x-envoy-upstream-service-time"}); +diff --git a/test/integration/http2_flood_integration_test.cc b/test/integration/http2_flood_integration_test.cc +index a5c9d864fb..779a4fd2a1 100644 +--- a/test/integration/http2_flood_integration_test.cc ++++ b/test/integration/http2_flood_integration_test.cc +@@ -338,7 +338,11 @@ TEST_P(Http2FloodMitigationTest, Data) { + // 9-byte frame header; 10 bytes per data frame, 10000 bytes total. The output buffer should also + // contain response headers, which should be less than 100 bytes. + EXPECT_LE(10000, buffer_factory->maxBufferSize()); ++#if defined(ALIMESH) ++ EXPECT_GE(20000, buffer_factory->maxBufferSize()); ++#else + EXPECT_GE(10100, buffer_factory->maxBufferSize()); ++#endif + + // The response pipeline input buffer could end up with the full upstream response in 1 go, but + // there are no guarantees of that being the case. +diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc +index dac1ce06c7..4d520b91ff 100644 +--- a/test/integration/http_integration.cc ++++ b/test/integration/http_integration.cc +@@ -560,7 +560,12 @@ void HttpIntegrationTest::testRouterUpstreamProtocolError(const std::string& exp + // TODO(mattklein123): Waiting for exact amount of data is a hack. This needs to + // be fixed. + std::string data; ++#if defined(ALIMESH) ++ // We added some custom TRI headers, so the request data changed. ++ ASSERT_TRUE(fake_upstream_connection->waitForData(247, &data)); ++#else + ASSERT_TRUE(fake_upstream_connection->waitForData(187, &data)); ++#endif + ASSERT_TRUE(fake_upstream_connection->write("bad protocol data!")); + ASSERT_TRUE(fake_upstream_connection->waitForDisconnect()); + ASSERT_TRUE(codec_client_->waitForDisconnect()); +@@ -665,6 +670,32 @@ void HttpIntegrationTest::testRouterVirtualClusters() { + test_server_->waitForCounterEq("vhost.integration.vcluster.other.upstream_rq_total", 1); + } + ++// Make sure route level stats are generated correctly. ++void HttpIntegrationTest::testRouteStats() { ++ config_helper_.addConfigModifier( ++ [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& ++ hcm) { ++ auto* route_config = hcm.mutable_route_config(); ++ ASSERT_EQ(1, route_config->virtual_hosts_size()); ++ auto* virtual_host = route_config->mutable_virtual_hosts(0); ++ auto* route = virtual_host->mutable_routes(0); ++ route->set_stat_prefix("test_route"); ++ }); ++ initialize(); ++ ++ codec_client_ = makeHttpConnection(lookupPort("http")); ++ Http::TestRequestHeaderMapImpl request_headers{{":method", "POST"}, ++ {":path", "/test/long/url"}, ++ {":scheme", "http"}, ++ {":authority", "sni.lyft.com"}}; ++ ++ auto response = sendRequestAndWaitForResponse(request_headers, 0, default_response_headers_, 0); ++ checkSimpleRequestSuccess(0, 0, response.get()); ++ ++ test_server_->waitForCounterEq("vhost.integration.route.test_route.upstream_rq_total", 1); ++ test_server_->waitForCounterEq("vhost.integration.route.test_route.upstream_rq_completed", 1); ++} ++ + void HttpIntegrationTest::testRouterUpstreamDisconnectBeforeRequestComplete() { + initialize(); + codec_client_ = makeHttpConnection(lookupPort("http")); +@@ -1273,10 +1304,15 @@ void HttpIntegrationTest::testManyRequestHeaders(std::chrono::milliseconds time) + {Http::Headers::get().Path, "/test/long/url"}, + {Http::Headers::get().Scheme, "http"}, + {Http::Headers::get().Host, "host"}}); +- ++#if defined(ALIMESH) ++ for (int i = 0; i < 9000; i++) { ++ big_headers->addCopy(Http::LowerCaseString(std::to_string(i)), std::string(0, 'a')); ++ } ++#else + for (int i = 0; i < 10000; i++) { + big_headers->addCopy(Http::LowerCaseString(std::to_string(i)), std::string(0, 'a')); + } ++#endif + initialize(); + + codec_client_ = makeHttpConnection(lookupPort("http")); +diff --git a/test/integration/http_integration.h b/test/integration/http_integration.h +index 6b01dd1b70..1deb5796c8 100644 +--- a/test/integration/http_integration.h ++++ b/test/integration/http_integration.h +@@ -201,6 +201,7 @@ protected: + void testRouterNotFound(); + void testRouterNotFoundWithBody(); + void testRouterVirtualClusters(); ++ void testRouteStats(); + void testRouterUpstreamProtocolError(const std::string&, const std::string&); + + void testRouterRequestAndResponseWithBody( +diff --git a/test/integration/integration_test.cc b/test/integration/integration_test.cc +index 5e8d025aa1..7eb96d4d73 100644 +--- a/test/integration/integration_test.cc ++++ b/test/integration/integration_test.cc +@@ -1278,6 +1278,8 @@ TEST_P(IntegrationTest, Connect) { + EXPECT_EQ(normalizeDate(response1), normalizeDate(response2)); + } + ++#if !defined(ALIMESH) ++ + // Test that Envoy by default returns HTTP code 502 on upstream protocol error. + TEST_P(IntegrationTest, UpstreamProtocolErrorDefault) { + testRouterUpstreamProtocolError("502", "UPE"); +@@ -1290,6 +1292,8 @@ TEST_P(IntegrationTest, UpstreamProtocolErrorRuntimeOverwrite) { + testRouterUpstreamProtocolError("503", "UC"); + } + ++#endif ++ + TEST_P(IntegrationTest, TestHead) { + initialize(); + +diff --git a/test/integration/protocol_integration_test.cc b/test/integration/protocol_integration_test.cc +index a33c7bc0e8..6079649674 100644 +--- a/test/integration/protocol_integration_test.cc ++++ b/test/integration/protocol_integration_test.cc +@@ -72,6 +72,8 @@ TEST_P(DownstreamProtocolIntegrationTest, RouterNotFound) { testRouterNotFound() + + TEST_P(ProtocolIntegrationTest, RouterVirtualClusters) { testRouterVirtualClusters(); } + ++TEST_P(ProtocolIntegrationTest, RouterStats) { testRouteStats(); } ++ + // Change the default route to be restrictive, and send a POST to an alternate route. + TEST_P(DownstreamProtocolIntegrationTest, RouterNotFoundBodyNoBuffer) { + testRouterNotFoundWithBody(); +@@ -3200,4 +3202,56 @@ TEST_P(ProtocolIntegrationTest, FragmentStrippedFromPathWithOverride) { + EXPECT_EQ("200", response->headers().getStatusValue()); + } + ++// Test buffering and then continuing after too many response bytes to buffer. ++TEST_P(ProtocolIntegrationTest, BufferContinue) { ++ // Bytes sent is configured for http/2 flow control windows. ++ if (upstreamProtocol() != Http::CodecType::HTTP2) { ++ return; ++ } ++ config_helper_.addConfigModifier( ++ [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& ++ hcm) -> void { ++ auto* route_config = hcm.mutable_route_config(); ++ auto* virtual_host = route_config->mutable_virtual_hosts(0); ++ auto* header = virtual_host->mutable_response_headers_to_add()->Add()->mutable_header(); ++ header->set_key("foo"); ++ header->set_value("bar"); ++ }); ++ ++ useAccessLog(); ++ config_helper_.addFilter("{ name: buffer-continue-filter, typed_config: { \"@type\": " ++ "type.googleapis.com/google.protobuf.Empty } }"); ++ config_helper_.setBufferLimits(1024, 1024); ++ initialize(); ++ ++ // Send the request. ++ codec_client_ = makeHttpConnection(lookupPort("http")); ++ auto encoder_decoder = codec_client_->startRequest(default_request_headers_); ++ auto downstream_request = &encoder_decoder.first; ++ auto response = std::move(encoder_decoder.second); ++ Buffer::OwnedImpl data("HTTP body content goes here"); ++ codec_client_->sendData(*downstream_request, data, true); ++ waitForNextUpstreamRequest(); ++ ++ // Send the response headers. ++ upstream_request_->encodeHeaders(default_response_headers_, false); ++ ++ // Now send an overly large response body. At some point, too much data will ++ // be buffered, the stream will be reset, and the connection will disconnect. ++ upstream_request_->encodeData(512, false); ++ upstream_request_->encodeData(1024 * 100, false); ++ ++ if (upstreamProtocol() == Http::CodecType::HTTP1) { ++ ASSERT_TRUE(fake_upstream_connection_->waitForDisconnect()); ++ } else { ++ ASSERT_TRUE(upstream_request_->waitForReset()); ++ ASSERT_TRUE(fake_upstream_connection_->close()); ++ ASSERT_TRUE(fake_upstream_connection_->waitForDisconnect()); ++ } ++ ++ ASSERT_TRUE(response->waitForEndStream()); ++ EXPECT_TRUE(response->complete()); ++ EXPECT_EQ("500", response->headers().getStatusValue()); ++} ++ + } // namespace Envoy +diff --git a/test/integration/redirect_integration_test.cc b/test/integration/redirect_integration_test.cc +index a88b83a191..813defeaba 100644 +--- a/test/integration/redirect_integration_test.cc ++++ b/test/integration/redirect_integration_test.cc +@@ -39,6 +39,15 @@ public: + ->set_value(3); + config_helper_.addVirtualHost(handle_max_3_hop); + ++ auto handle_by_direct_response = config_helper_.createVirtualHost("handle.direct.response"); ++ handle_by_direct_response.mutable_routes(0)->set_name("direct_response"); ++ handle_by_direct_response.mutable_routes(0)->mutable_direct_response()->set_status(204); ++ handle_by_direct_response.mutable_routes(0) ++ ->mutable_direct_response() ++ ->mutable_body() ++ ->set_inline_string(EMPTY_STRING); ++ config_helper_.addVirtualHost(handle_by_direct_response); ++ + HttpProtocolIntegrationTest::initialize(); + } + +@@ -597,6 +606,39 @@ TEST_P(RedirectIntegrationTest, InvalidRedirect) { + response->headers().get(test_header_key_)[0]->value().getStringView()); + } + ++TEST_P(RedirectIntegrationTest, InternalRedirectHandledByDirectResponse) { ++ useAccessLog("%RESPONSE_FLAGS% %RESPONSE_CODE% %RESPONSE_CODE_DETAILS% %RESP(test-header)%"); ++ // Validate that header sanitization is only called once. ++ config_helper_.addConfigModifier( ++ [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& ++ hcm) { hcm.set_via("via_value"); }); ++ initialize(); ++ ++ codec_client_ = makeHttpConnection(lookupPort("http")); ++ ++ default_request_headers_.setHost("handle.internal.redirect"); ++ IntegrationStreamDecoderPtr response = ++ codec_client_->makeHeaderOnlyRequest(default_request_headers_); ++ ++ waitForNextUpstreamRequest(); ++ ++ redirect_response_.setLocation("http://handle.direct.response/"); ++ upstream_request_->encodeHeaders(redirect_response_, true); ++ ++ ASSERT_TRUE(response->waitForEndStream()); ++ ASSERT_TRUE(response->complete()); ++ EXPECT_EQ("204", response->headers().getStatusValue()); ++ EXPECT_EQ(1, test_server_->counter("cluster.cluster_0.upstream_internal_redirect_succeeded_total") ++ ->value()); ++ // 302 was never returned downstream ++ EXPECT_EQ(0, test_server_->counter("http.config_test.downstream_rq_3xx")->value()); ++ EXPECT_EQ(1, test_server_->counter("http.config_test.downstream_rq_2xx")->value()); ++ EXPECT_THAT(waitForAccessLog(access_log_name_, 0), ++ HasSubstr("302 internal_redirect test-header-value\n")); ++ // No test header ++ EXPECT_THAT(waitForAccessLog(access_log_name_, 1), HasSubstr("204 direct_response -\n")); ++} ++ + INSTANTIATE_TEST_SUITE_P(Protocols, RedirectIntegrationTest, + testing::ValuesIn(HttpProtocolIntegrationTest::getProtocolTestParams()), + HttpProtocolIntegrationTest::protocolTestParamsToString); +diff --git a/test/mocks/http/mocks.h b/test/mocks/http/mocks.h +index 11db504141..8656f772a9 100644 +--- a/test/mocks/http/mocks.h ++++ b/test/mocks/http/mocks.h +@@ -838,7 +838,40 @@ MATCHER_P(HeaderMapEqual, rhs, "") { + } + + MATCHER_P(HeaderMapEqualRef, rhs, "") { +- const bool equal = (arg == *rhs); ++#if defined(ALIMESH) ++ bool equal = true; ++ ++ auto getHeaderItems = [](const Envoy::Http::HeaderMap& header, ++ std::vector>& dst) { ++ auto f = [&dst](const Envoy::Http::HeaderEntry& header) -> Envoy::Http::HeaderMap::Iterate { ++ dst.push_back(std::make_pair(header.key().getStringView(), header.value().getStringView())); ++ return Envoy::Http::HeaderMap::Iterate::Continue; ++ }; ++ ++ header.iterate(f); ++ }; ++ ++ std::vector> arg_header, rhs_header; ++ ++ getHeaderItems(arg, arg_header); ++ getHeaderItems((*rhs), rhs_header); ++ ++ auto i = arg_header.begin(); ++ auto j = rhs_header.begin(); ++ ++ for (; i != arg_header.end(); ++i, ++j) { ++ ++ if (i->first == "req-start-time") { ++ continue; ++ } ++ if (i->first != j->first || i->second != j->second) { ++ equal = false; ++ break; ++ } ++ } ++#else ++ const bool equal = (arg == *rhs) ++#endif + if (!equal) { + *result_listener << "\n" + << TestUtility::addLeftAndRightPadding("header map:") << "\n" +diff --git a/test/mocks/router/BUILD b/test/mocks/router/BUILD +index 1cfbbf669b..2a704b153d 100644 +--- a/test/mocks/router/BUILD ++++ b/test/mocks/router/BUILD +@@ -16,6 +16,7 @@ envoy_cc_mock( + "//envoy/event:dispatcher_interface", + "//envoy/json:json_object_interface", + "//envoy/local_info:local_info_interface", ++ "//envoy/router:cluster_specifier_plugin_interface", + "//envoy/router:route_config_provider_manager_interface", + "//envoy/router:router_interface", + "//envoy/router:router_ratelimit_interface", +diff --git a/test/mocks/router/mocks.cc b/test/mocks/router/mocks.cc +index 8ab3d486fb..b78b29bca8 100644 +--- a/test/mocks/router/mocks.cc ++++ b/test/mocks/router/mocks.cc +@@ -27,6 +27,12 @@ MockInternalRedirectPolicy::MockInternalRedirectPolicy() { + ON_CALL(*this, enabled()).WillByDefault(Return(false)); + } + ++#if defined(ALIMESH) ++MockInternalActiveRedirectPolicy::MockInternalActiveRedirectPolicy() { ++ ON_CALL(*this, enabled()).WillByDefault(Return(false)); ++} ++#endif ++ + MockRetryState::MockRetryState() = default; + + void MockRetryState::expectHeadersRetry() { +@@ -103,6 +109,11 @@ MockRouteEntry::MockRouteEntry() { + ON_CALL(*this, hedgePolicy()).WillByDefault(ReturnRef(hedge_policy_)); + ON_CALL(*this, routeName()).WillByDefault(ReturnRef(route_name_)); + ON_CALL(*this, connectConfig()).WillByDefault(ReturnRef(connect_config_)); ++ ++#if defined(ALIMESH) ++ ON_CALL(*this, internalActiveRedirectPolicy()) ++ .WillByDefault(ReturnRef(internal_active_redirect_policy_)); ++#endif + } + + MockRouteEntry::~MockRouteEntry() = default; +@@ -157,5 +168,14 @@ MockScopedRouteConfigProvider::~MockScopedRouteConfigProvider() = default; + MockGenericConnectionPoolCallbacks::MockGenericConnectionPoolCallbacks() { + ON_CALL(*this, upstreamToDownstream()).WillByDefault(ReturnRef(upstream_to_downstream_)); + } ++ ++MockClusterSpecifierPlugin::MockClusterSpecifierPlugin() { ++ ON_CALL(*this, route(_, _)).WillByDefault(Return(nullptr)); ++} ++ ++MockClusterSpecifierPluginFactoryConfig::MockClusterSpecifierPluginFactoryConfig() { ++ ON_CALL(*this, createClusterSpecifierPlugin(_, _)).WillByDefault(Return(nullptr)); ++} ++ + } // namespace Router + } // namespace Envoy +diff --git a/test/mocks/router/mocks.h b/test/mocks/router/mocks.h +index e9ccd1de05..ced5d02c80 100644 +--- a/test/mocks/router/mocks.h ++++ b/test/mocks/router/mocks.h +@@ -17,6 +17,7 @@ + #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h" + #include "envoy/http/hash_policy.h" + #include "envoy/local_info/local_info.h" ++#include "envoy/router/cluster_specifier_plugin.h" + #include "envoy/router/rds.h" + #include "envoy/router/route_config_provider_manager.h" + #include "envoy/router/router.h" +@@ -156,6 +157,22 @@ public: + MOCK_METHOD(bool, isCrossSchemeRedirectAllowed, (), (const)); + }; + ++#if defined(ALIMESH) ++class MockInternalActiveRedirectPolicy : public InternalActiveRedirectPolicy { ++public: ++ MockInternalActiveRedirectPolicy(); ++ MOCK_METHOD(bool, enabled, (), (const)); ++ MOCK_METHOD(bool, shouldRedirectForResponseCode, (const Http::Code& response_code), (const)); ++ MOCK_METHOD(std::vector, predicates, (), (const)); ++ MOCK_METHOD(uint32_t, maxInternalRedirects, (), (const)); ++ MOCK_METHOD(bool, isCrossSchemeRedirectAllowed, (), (const)); ++ MOCK_METHOD(void, evaluateHeaders, (Http::HeaderMap&, const StreamInfo::StreamInfo*), (const)); ++ MOCK_METHOD(std::string, redirectUrl, (absl::optional), (const)); ++ MOCK_METHOD(bool, forcedUseOriginalHost, (), (const)); ++ MOCK_METHOD(bool, forcedAddHeaderBeforeRouteMatcher, (), (const)); ++}; ++#endif ++ + class MockInternalRedirectPredicate : public InternalRedirectPredicate { + public: + MOCK_METHOD(bool, acceptTargetRoute, (StreamInfo::FilterState&, absl::string_view, bool, bool)); +@@ -263,9 +280,11 @@ public: + class TestVirtualCluster : public VirtualCluster { + public: + // Router::VirtualCluster ++ const absl::optional& name() const override { return name_; } + Stats::StatName statName() const override { return stat_name_.statName(); } + VirtualClusterStats& stats() const override { return stats_; } + ++ const absl::optional name_ = "fake_virtual_cluster"; + Stats::TestUtil::TestSymbolTable symbol_table_; + Stats::StatNameManagedStorage stat_name_{"fake_virtual_cluster", *symbol_table_}; + Stats::IsolatedStoreImpl stats_store_; +@@ -390,6 +409,7 @@ public: + MOCK_METHOD(const VirtualCluster*, virtualCluster, (const Http::HeaderMap& headers), (const)); + MOCK_METHOD(const VirtualHost&, virtualHost, (), (const)); + MOCK_METHOD(bool, autoHostRewrite, (), (const)); ++ MOCK_METHOD(bool, appendXfh, (), (const)); + MOCK_METHOD((const std::multimap&), opaqueConfig, (), (const)); + MOCK_METHOD(bool, includeVirtualHostRateLimits, (), (const)); + MOCK_METHOD(const CorsPolicy*, corsPolicy, (), (const)); +@@ -402,6 +422,14 @@ public: + MOCK_METHOD(const UpgradeMap&, upgradeMap, (), (const)); + MOCK_METHOD(const std::string&, routeName, (), (const)); + ++#if defined(ALIMESH) ++ MOCK_METHOD(const InternalActiveRedirectPolicy&, internalActiveRedirectPolicy, (), (const)); ++#endif ++ ++ const RouteStatsContextOptRef routeStatsContext() const override { ++ return RouteStatsContextOptRef(); ++ } ++ + std::string cluster_name_{"fake_cluster"}; + std::string route_name_{"fake_route_name"}; + std::multimap opaque_config_; +@@ -419,6 +447,10 @@ public: + testing::NiceMock path_match_criterion_; + UpgradeMap upgrade_map_; + absl::optional connect_config_; ++ ++#if defined(ALIMESH) ++ testing::NiceMock internal_active_redirect_policy_; ++#endif + }; + + class MockDecorator : public Decorator { +@@ -568,7 +600,7 @@ class MockGenericConnPool : public GenericConnPool { + + class MockUpstreamToDownstream : public UpstreamToDownstream { + public: +- MOCK_METHOD(const RouteEntry&, routeEntry, (), (const)); ++ MOCK_METHOD(const Route&, route, (), (const)); + MOCK_METHOD(const Network::Connection&, connection, (), (const)); + + MOCK_METHOD(void, decodeData, (Buffer::Instance&, bool)); +@@ -601,5 +633,27 @@ public: + NiceMock upstream_to_downstream_; + }; + ++class MockClusterSpecifierPlugin : public ClusterSpecifierPlugin { ++public: ++ MockClusterSpecifierPlugin(); ++ ++ MOCK_METHOD(RouteConstSharedPtr, route, ++ (const RouteEntry& parent, const Http::RequestHeaderMap& header), (const)); ++}; ++ ++class MockClusterSpecifierPluginFactoryConfig : public ClusterSpecifierPluginFactoryConfig { ++public: ++ MockClusterSpecifierPluginFactoryConfig(); ++ MOCK_METHOD(ClusterSpecifierPluginSharedPtr, createClusterSpecifierPlugin, ++ (const Protobuf::Message& config, ++ Server::Configuration::CommonFactoryContext& context)); ++ ++ ProtobufTypes::MessagePtr createEmptyConfigProto() override { ++ return std::make_unique(); ++ } ++ ++ std::string name() const override { return "envoy.router.cluster_specifier_plugin.mock"; } ++}; ++ + } // namespace Router + } // namespace Envoy +diff --git a/test/mocks/router/router_filter_interface.cc b/test/mocks/router/router_filter_interface.cc +index 9d175ee6cb..1e025fa431 100644 +--- a/test/mocks/router/router_filter_interface.cc ++++ b/test/mocks/router/router_filter_interface.cc +@@ -20,9 +20,9 @@ MockRouterFilterInterface::MockRouterFilterInterface() + ON_CALL(*this, upstreamRequests()).WillByDefault(ReturnRef(requests_)); + EXPECT_CALL(callbacks_.dispatcher_, pushTrackedObject(_)).Times(AnyNumber()); + EXPECT_CALL(callbacks_.dispatcher_, popTrackedObject(_)).Times(AnyNumber()); +- ON_CALL(*this, routeEntry()).WillByDefault(Return(&route_entry_)); ++ ON_CALL(*this, route()).WillByDefault(Return(&route_)); + ON_CALL(callbacks_, connection()).WillByDefault(Return(&client_connection_)); +- route_entry_.connect_config_.emplace(RouteEntry::ConnectConfig()); ++ route_.route_entry_.connect_config_.emplace(RouteEntry::ConnectConfig()); + } + + MockRouterFilterInterface::~MockRouterFilterInterface() = default; +diff --git a/test/mocks/router/router_filter_interface.h b/test/mocks/router/router_filter_interface.h +index d1349a4103..1a662e24ae 100644 +--- a/test/mocks/router/router_filter_interface.h ++++ b/test/mocks/router/router_filter_interface.h +@@ -45,13 +45,17 @@ public: + MOCK_METHOD(bool, downstreamEndStream, (), (const)); + MOCK_METHOD(uint32_t, attemptCount, (), (const)); + MOCK_METHOD(const VirtualCluster*, requestVcluster, (), (const)); +- MOCK_METHOD(const RouteEntry*, routeEntry, (), (const)); ++ MOCK_METHOD(const Route*, route, (), (const)); + MOCK_METHOD(const std::list&, upstreamRequests, (), (const)); + MOCK_METHOD(const UpstreamRequest*, finalUpstreamRequest, (), (const)); + MOCK_METHOD(TimeSource&, timeSource, ()); + ++ const RouteStatsContextOptRef routeStatsContext() const override { ++ return RouteStatsContextOptRef(); ++ } ++ + NiceMock callbacks_; +- NiceMock route_entry_; ++ NiceMock route_; + NiceMock client_connection_; + + envoy::extensions::filters::http::router::v3::Router router_proto; +diff --git a/test/mocks/stream_info/mocks.cc b/test/mocks/stream_info/mocks.cc +index 49bdf235a5..77b7bb00f5 100644 +--- a/test/mocks/stream_info/mocks.cc ++++ b/test/mocks/stream_info/mocks.cc +@@ -109,7 +109,12 @@ MockStreamInfo::MockStreamInfo() + ON_CALL(*this, setRouteName(_)).WillByDefault(Invoke([this](const absl::string_view route_name) { + route_name_ = std::string(route_name); + })); ++ ON_CALL(*this, setVirtualClusterName(_)) ++ .WillByDefault(Invoke([this](const absl::optional& virtual_cluster_name) { ++ virtual_cluster_name_ = virtual_cluster_name; ++ })); + ON_CALL(*this, getRouteName()).WillByDefault(ReturnRef(route_name_)); ++ ON_CALL(*this, virtualClusterName()).WillByDefault(ReturnRef(virtual_cluster_name_)); + ON_CALL(*this, upstreamTransportFailureReason()) + .WillByDefault(ReturnRef(upstream_transport_failure_reason_)); + ON_CALL(*this, setConnectionID(_)).WillByDefault(Invoke([this](uint64_t id) { +diff --git a/test/mocks/stream_info/mocks.h b/test/mocks/stream_info/mocks.h +index 2d296f9697..c72285f8de 100644 +--- a/test/mocks/stream_info/mocks.h ++++ b/test/mocks/stream_info/mocks.h +@@ -49,7 +49,10 @@ public: + MOCK_METHOD(void, addBytesReceived, (uint64_t)); + MOCK_METHOD(uint64_t, bytesReceived, (), (const)); + MOCK_METHOD(void, setRouteName, (absl::string_view route_name)); ++ MOCK_METHOD(void, setVirtualClusterName, ++ (const absl::optional& virtual_cluster_name)); + MOCK_METHOD(const std::string&, getRouteName, (), (const)); ++ MOCK_METHOD(const absl::optional&, virtualClusterName, (), (const)); + MOCK_METHOD(absl::optional, protocol, (), (const)); + MOCK_METHOD(void, protocol, (Http::Protocol protocol)); + MOCK_METHOD(absl::optional, responseCode, (), (const)); +@@ -132,6 +135,7 @@ public: + std::string filter_chain_name_; + absl::optional upstream_connection_id_; + absl::optional attempt_count_; ++ absl::optional virtual_cluster_name_; + }; + + } // namespace StreamInfo +diff --git a/test/mocks/thread_local/mocks.h b/test/mocks/thread_local/mocks.h +index 3fa0f8d347..6696703e89 100644 +--- a/test/mocks/thread_local/mocks.h ++++ b/test/mocks/thread_local/mocks.h +@@ -73,6 +73,7 @@ public: + EXPECT_TRUE(was_set_); + parent_.runOnAllThreads([cb, this]() { cb(parent_.data_[index_]); }, main_callback); + } ++ bool isShutdown() const override { return parent_.shutdown_; } + + void set(InitializeCb cb) override { + was_set_ = true; +diff --git a/test/mocks/upstream/host.h b/test/mocks/upstream/host.h +index cd6cc8e21b..698e72c2c2 100644 +--- a/test/mocks/upstream/host.h ++++ b/test/mocks/upstream/host.h +@@ -35,6 +35,10 @@ public: + MOCK_METHOD(double, successRate, (DetectorHostMonitor::SuccessRateMonitorType type), (const)); + MOCK_METHOD(void, successRate, + (DetectorHostMonitor::SuccessRateMonitorType type, double new_success_rate)); ++ ++#if defined(ALIMESH) ++ MOCK_METHOD(void, forceEjectHost, ()); ++#endif + }; + + class MockEventLogger : public EventLogger { +diff --git a/test/server/BUILD b/test/server/BUILD +index 952131ac02..3c73052062 100644 +--- a/test/server/BUILD ++++ b/test/server/BUILD +@@ -9,7 +9,7 @@ load( + "envoy_select_hot_restart", + ) + load("//source/extensions:all_extensions.bzl", "envoy_all_extensions") +-load("//bazel:repositories.bzl", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") ++load("//bazel:repositories.bzl", "DARWIN_SKIP_TARGETS", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") + + licenses(["notice"]) # Apache 2 + +@@ -377,6 +377,7 @@ envoy_cc_fuzz_test( + ] + select({ + "//bazel:windows_x86_64": envoy_all_extensions(WINDOWS_SKIP_TARGETS), + "//bazel:linux_ppc": envoy_all_extensions(PPC_SKIP_TARGETS), ++ "//bazel:darwin": envoy_all_extensions(DARWIN_SKIP_TARGETS), + "//bazel:gcc_build": [], + "//conditions:default": envoy_all_extensions(), + }), +diff --git a/test/server/config_validation/BUILD b/test/server/config_validation/BUILD +index 626b0b9381..0874ffc288 100644 +--- a/test/server/config_validation/BUILD ++++ b/test/server/config_validation/BUILD +@@ -1,6 +1,6 @@ + load("//bazel:envoy_build_system.bzl", "envoy_cc_fuzz_test", "envoy_cc_test", "envoy_cc_test_library", "envoy_package", "envoy_proto_library") + load("//source/extensions:all_extensions.bzl", "envoy_all_extensions") +-load("//bazel:repositories.bzl", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") ++load("//bazel:repositories.bzl", "DARWIN_SKIP_TARGETS", "PPC_SKIP_TARGETS", "WINDOWS_SKIP_TARGETS") + + licenses(["notice"]) # Apache 2 + +@@ -92,6 +92,7 @@ envoy_cc_fuzz_test( + ] + select({ + "//bazel:windows_x86_64": envoy_all_extensions(WINDOWS_SKIP_TARGETS), + "//bazel:linux_ppc": envoy_all_extensions(PPC_SKIP_TARGETS), ++ "//bazel:darwin": envoy_all_extensions(DARWIN_SKIP_TARGETS), + "//bazel:gcc_build": [], + "//conditions:default": envoy_all_extensions(), + }), +diff --git a/test/test_common/delegating_route_utility.h b/test/test_common/delegating_route_utility.h +index 2189f88946..4a12b75f32 100644 +--- a/test/test_common/delegating_route_utility.h ++++ b/test/test_common/delegating_route_utility.h +@@ -13,6 +13,9 @@ public: + : DelegatingRouteEntry(std::move(base_route)), custom_cluster_name_(cluster_name_override) {} + + const std::string& clusterName() const override { return custom_cluster_name_; } ++ const RouteStatsContextOptRef routeStatsContext() const override { ++ return RouteStatsContextOptRef(); ++ } + + private: + const std::string custom_cluster_name_; +diff --git a/test/test_common/status_utility.h b/test/test_common/status_utility.h +index 7611830b26..fae63ce3bb 100644 +--- a/test/test_common/status_utility.h ++++ b/test/test_common/status_utility.h +@@ -38,5 +38,115 @@ MATCHER_P(StatusIs, expected_code, "") { + return true; + } + ++// A polymorphic matcher class for matching absl::Status or absl::StatusOr. ++// Not intended for direct use, see HasStatus, HasStatusCode, HasStatusMessage and IsOk ++// below. ++class StatusMatcher { ++public: ++ StatusMatcher(::testing::Matcher matcher) : matcher_(matcher) {} ++ ++ // NOLINTNEXTLINE(readability-identifier-naming) ++ bool MatchAndExplain(absl::Status status, ::testing::MatchResultListener* listener) const { ++ return matcher_.MatchAndExplain(status, listener); ++ } ++ ++ template ++ // NOLINTNEXTLINE(readability-identifier-naming) ++ bool MatchAndExplain(const absl::StatusOr& status_or, ++ ::testing::MatchResultListener* listener) const { ++ return ::testing::ExplainMatchResult( ++ ::testing::Property("status", &absl::StatusOr::status, matcher_), status_or, listener); ++ } ++ // NOLINTNEXTLINE(readability-identifier-naming) ++ void DescribeTo(::std::ostream* os) const { matcher_.DescribeTo(os); } ++ // NOLINTNEXTLINE(readability-identifier-naming) ++ void DescribeNegationTo(::std::ostream* os) const { ++ *os << "not "; ++ matcher_.DescribeTo(os); ++ } ++ ++private: ++ ::testing::Matcher matcher_; ++}; ++ ++// Match status code in an absl::StatusOr or absl::Status, allowing arbitrary matchers, ++// e.g. ++// EXPECT_THAT(some_status_or, HasStatusCode(AnyOf(absl::StatusCode::kOk, ++// absl::StatusCode::kInvalidArgument))); ++template ++// NOLINTNEXTLINE(readability-identifier-naming) ++::testing::PolymorphicMatcher HasStatusCode(InnerMatcher m) { ++ return ::testing::MakePolymorphicMatcher(StatusMatcher(::testing::SafeMatcherCast( ++ ::testing::Property("code", &absl::Status::code, m)))); ++} ++ ++// Match status message in an absl::StatusOr or absl::Status, allowing arbitrary matchers, ++// e.g. ++// EXPECT_THAT(some_status_or, HasStatusMessage(HasSubstr("cheese"))); ++template ++// NOLINTNEXTLINE(readability-identifier-naming) ++::testing::PolymorphicMatcher HasStatusMessage(InnerMatcher m) { ++ return ::testing::MakePolymorphicMatcher(StatusMatcher(::testing::SafeMatcherCast( ++ ::testing::Property("message", &absl::Status::message, m)))); ++} ++ ++// Match the status of an absl::StatusOr or absl::Status, e.g. ++// EXPECT_THAT(some_status_or, HasStatus(absl::InvalidArgumentError("oh no"))); ++// One may also use a Status matcher, but see the other HasStatus below for a ++// more readable version of that. ++template ++// NOLINTNEXTLINE(readability-identifier-naming) ++::testing::PolymorphicMatcher HasStatus(InnerMatcher m) { ++ return ::testing::MakePolymorphicMatcher( ++ StatusMatcher(::testing::SafeMatcherCast(m))); ++} ++ ++// Match the code and message of an absl::StatusOr or absl::Status, e.g. ++// EXPECT_THAT(some_status_or, HasStatus(absl::StatusCode::kInvalidArgument, HasSubstr("cheese"))); ++template ++// NOLINTNEXTLINE(readability-identifier-naming) ++::testing::PolymorphicMatcher HasStatus(InnerMatcherCode code_matcher, ++ InnerMatcherMessage message_matcher) { ++ return ::testing::MakePolymorphicMatcher(StatusMatcher(::testing::SafeMatcherCast( ++ AllOf(::testing::Property("code", &absl::Status::code, code_matcher), ++ ::testing::Property("message", &absl::Status::message, message_matcher))))); ++} ++ ++// Check that an absl::Status or absl::StatusOr is OK. ++// ++// For example: ++// ++// StatusOr status_or(absl::InvalidArgumentError("bad argument!")); ++// EXPECT_THAT(status_or, IsOk()); // fails! ++// ++// NOLINTNEXTLINE(readability-identifier-naming) ++inline ::testing::PolymorphicMatcher IsOk() { ++ return HasStatusCode(absl::StatusCode::kOk); ++} ++ ++#ifndef EXPECT_OK ++// Fails if an absl::Status or absl::StatusOr is not OK. ++// ++// For example: ++// ++// StatusOr status_or(absl::InvalidArgumentError("bad argument!")); ++// EXPECT_OK(status_or); // fails! ++// absl::Status status{absl::OkStatus()}; ++// EXPECT_OK(status); // passes! ++#define EXPECT_OK(v) EXPECT_THAT((v), ::Envoy::StatusHelpers::IsOk()) ++#endif // EXPECT_OK ++ ++#ifndef ASSERT_OK ++// Asserts if an absl::Status or absl::StatusOr is not OK. ++// ++// For example: ++// ++// StatusOr status_or(absl::InvalidArgumentError("bad argument!")); ++// ASSERT_OK(status_or); // asserts! ++// absl::Status status{absl::OkStatus()}; ++// ASSERT_OK(status); // passes! ++#define ASSERT_OK(v) ASSERT_THAT((v), ::Envoy::StatusHelpers::IsOk()) ++#endif // ASSERT_OK ++ + } // namespace StatusHelpers + } // namespace Envoy +diff --git a/test/test_common/status_utility_test.cc b/test/test_common/status_utility_test.cc +new file mode 100644 +index 0000000000..71ee8a5c67 +--- /dev/null ++++ b/test/test_common/status_utility_test.cc +@@ -0,0 +1,141 @@ ++#include "test/test_common/status_utility.h" ++ ++namespace Envoy { ++namespace StatusHelpers { ++ ++using ::testing::HasSubstr; ++ ++template ++std::string expectThatOutput(const T& value, MatcherT matcher) { ++ auto m = ::testing::SafeMatcherCast(matcher); ++ if (m.Matches(value)) { ++ return ""; ++ } ++ ::std::stringstream ss; ++ ss << "Value of: [variable_name]" << std::endl; ++ ss << "Expected: "; ++ m.DescribeTo(&ss); ++ ss << std::endl << "Actual: " << ::testing::PrintToString(value); ++ ::testing::StringMatchResultListener listener; ++ ::testing::ExplainMatchResult(matcher, value, &listener); ++ ss << std::endl << listener.str(); ++ return ss.str(); ++} ++ ++TEST(StatusUtilityTest, ExpectOkForStatus) { EXPECT_OK(absl::OkStatus()); } ++ ++TEST(StatusUtilityTest, ExpectOkForStatusOr) { EXPECT_OK(absl::StatusOr{5}); } ++ ++TEST(StatusUtilityTest, IsOkFailureForStatus) { ++ auto err = expectThatOutput(absl::FailedPreconditionError("whatever"), IsOk()); ++ EXPECT_THAT(err, AllOf(HasSubstr("Expected: is an object whose property `code` is equal to OK"), ++ HasSubstr("Actual: FAILED_PRECONDITION: whatever"), ++ HasSubstr("whose property `code` is FAILED_PRECONDITION"))); ++} ++ ++TEST(StatusUtilityTest, IsOkFailureForStatusOr) { ++ auto err = ++ expectThatOutput(absl::StatusOr{absl::FailedPreconditionError("whatever")}, IsOk()); ++ EXPECT_THAT(err, AllOf(HasSubstr("whose property `status` is FAILED_PRECONDITION: whatever"), ++ HasSubstr("whose property `code` is FAILED_PRECONDITION"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusCodeSuccessForStatus) { ++ EXPECT_THAT(absl::FailedPreconditionError("whatever"), ++ HasStatusCode(absl::StatusCode::kFailedPrecondition)); ++} ++ ++TEST(StatusUtilityTest, HasStatusMessageSuccessForStatus) { ++ EXPECT_THAT(absl::FailedPreconditionError("whatever"), HasStatusMessage(HasSubstr("whatever"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusCodeFailureForStatusOr) { ++ auto err = expectThatOutput(absl::StatusOr{5}, ++ HasStatusCode(absl::StatusCode::kFailedPrecondition)); ++ EXPECT_THAT( ++ err, ++ AllOf( ++ HasSubstr("Expected: is an object whose property `code` is equal to FAILED_PRECONDITION"), ++ HasSubstr("whose property `status` is OK"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusMessageFailureForStatus) { ++ auto err = expectThatOutput(absl::InvalidArgumentError("oh no"), HasStatusMessage("whatever")); ++ EXPECT_THAT(err, HasSubstr("whose property `message` is \"oh no\"")); ++} ++ ++TEST(StatusUtilityTest, HasStatusFailureForStatusOr) { ++ auto err = expectThatOutput(absl::StatusOr{absl::InvalidArgumentError("oh no")}, ++ HasStatus(absl::OkStatus())); ++ EXPECT_THAT(err, AllOf(HasSubstr("Expected: is equal to OK"), ++ HasSubstr("whose property `status` is INVALID_ARGUMENT: oh no"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusFailureForStatus) { ++ auto err = expectThatOutput(absl::InvalidArgumentError("oh no"), HasStatus(absl::OkStatus())); ++ EXPECT_THAT(err, AllOf(HasSubstr("Expected: is equal to OK"), ++ HasSubstr("Actual: INVALID_ARGUMENT: oh no"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusSuccessForStatusOr) { ++ auto status = absl::InvalidArgumentError("oh no"); ++ EXPECT_THAT(absl::StatusOr{status}, HasStatus(status)); ++} ++ ++TEST(StatusUtilityTest, HasStatusSuccessForStatus) { ++ auto status = absl::InvalidArgumentError("oh no"); ++ EXPECT_THAT(status, HasStatus(status)); ++} ++ ++TEST(StatusUtilityTest, HasStatusTwoParamsFailureForStatusOr) { ++ auto err = expectThatOutput(absl::StatusOr{absl::InvalidArgumentError("oh no")}, ++ HasStatus(absl::StatusCode::kOk, HasSubstr("whatever"))); ++ EXPECT_THAT( ++ err, ++ AllOf(HasSubstr("Expected: (is an object whose property `code` is equal to OK) and (is an " ++ "object whose property `message` has substring \"whatever\")"), ++ HasSubstr("whose property `status` is INVALID_ARGUMENT: oh no"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusTwoParamsFailureForStatus) { ++ auto err = expectThatOutput(absl::InvalidArgumentError("oh no"), ++ HasStatus(absl::StatusCode::kOk, HasSubstr("whatever"))); ++ EXPECT_THAT( ++ err, ++ AllOf(HasSubstr("Expected: (is an object whose property `code` is equal to OK) and (is an " ++ "object whose property `message` has substring \"whatever\")"), ++ HasSubstr("Actual: INVALID_ARGUMENT: oh no"), ++ HasSubstr("whose property `code` is INVALID_ARGUMENT"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusTwoParamsSuccessForStatusOr) { ++ auto err = absl::InvalidArgumentError("oh no"); ++ auto status_or = absl::StatusOr{err}; ++ EXPECT_THAT(status_or, HasStatus(absl::StatusCode::kInvalidArgument, HasSubstr("oh no"))); ++} ++ ++TEST(StatusUtilityTest, HasStatusTwoParamsSuccessForStatus) { ++ auto err = absl::InvalidArgumentError("oh no"); ++ EXPECT_THAT(err, HasStatus(absl::StatusCode::kInvalidArgument, HasSubstr("oh no"))); ++} ++ ++TEST(StatusUtilityTest, IsOkAndHoldsSuccess) { ++ absl::StatusOr five = 5; ++ EXPECT_THAT(five, IsOkAndHolds(5)); ++} ++ ++TEST(StatusUtilityTest, IsOkAndHoldsFailureByValue) { ++ ::testing::StringMatchResultListener listener; ++ ::testing::ExplainMatchResult(IsOkAndHolds(5), absl::StatusOr{6}, &listener); ++ EXPECT_EQ("which has wrong value: 6", listener.str()); ++} ++ ++TEST(StatusUtilityTest, IsOkAndHoldsFailureByCode) { ++ ::testing::StringMatchResultListener listener; ++ ::testing::ExplainMatchResult( ++ IsOkAndHolds(5), absl::StatusOr{absl::FailedPreconditionError("oh no")}, &listener); ++ EXPECT_EQ("which has unexpected status: FAILED_PRECONDITION: oh no", listener.str()); ++} ++ ++} // namespace StatusHelpers ++} // namespace Envoy +diff --git a/test/test_common/utility.cc b/test/test_common/utility.cc +index fe0db0bcf7..4d5b193355 100644 +--- a/test/test_common/utility.cc ++++ b/test/test_common/utility.cc +@@ -71,6 +71,12 @@ bool TestUtility::headerMapEqualIgnoreOrder(const Http::HeaderMap& lhs, + absl::flat_hash_set rhs_keys; + lhs.iterate([&lhs_keys](const Http::HeaderEntry& header) -> Http::HeaderMap::Iterate { + const std::string key{header.key().getStringView()}; ++#if defined(ALIMESH) ++ if (key == Http::CustomHeaders::get().AliExtendedValues.TriStartTime.get() || ++ key == Http::CustomHeaders::get().AliExtendedValues.EnvoyOriginalHost.get()) { ++ return Http::HeaderMap::Iterate::Continue; ++ } ++#endif + lhs_keys.insert(key); + return Http::HeaderMap::Iterate::Continue; + }); +diff --git a/tools/code_format/check_format.py b/tools/code_format/check_format.py +index d01897fc33..ed193869ce 100755 +--- a/tools/code_format/check_format.py ++++ b/tools/code_format/check_format.py +@@ -356,6 +356,11 @@ class FormatChecker: + error_messages = [] + + clang_format_abs_path = self.look_path(CLANG_FORMAT_PATH) ++ print('clang format path: {}'.format(clang_format_abs_path)) ++ command = "%s --version" % (clang_format_abs_path) ++ if os.system(command) != 0: ++ error_messages.append("clang-format version error") ++ + if clang_format_abs_path: + if not self.executable_by_others(clang_format_abs_path): + error_messages.append( +diff --git a/tools/code_format/check_shellcheck_format.sh b/tools/code_format/check_shellcheck_format.sh +index b09ba6cb08..9b1e08dd8c 100755 +--- a/tools/code_format/check_shellcheck_format.sh ++++ b/tools/code_format/check_shellcheck_format.sh +@@ -1,6 +1,6 @@ + #!/bin/bash -e + +-EXCLUDED_SHELLFILES=${EXCLUDED_SHELLFILES:-".rst$|.md$"} ++EXCLUDED_SHELLFILES=${EXCLUDED_SHELLFILES:-"^.github|.rst$|.md$|.*aone.*|xsdk.BUILD"} + SHEBANG_RE='^#!/bin/bash|^#!/bin/sh|^#!/usr/bin/env bash|^#!/usr/bin/env sh' + + +diff --git a/tools/proto_format/proto_sync.py b/tools/proto_format/proto_sync.py +index 8d878309c6..40983f8d59 100755 +--- a/tools/proto_format/proto_sync.py ++++ b/tools/proto_format/proto_sync.py +@@ -44,6 +44,9 @@ CONTRIB_V3_ALLOW_LIST = [ + 'envoy.extensions.filters.network.kafka_broker.v3', + 'envoy.extensions.filters.network.mysql_proxy.v3', + 'envoy.extensions.filters.network.rocketmq_proxy.v3', ++ ++ # Ingress gateway. ++ 'envoy.extensions.filters.http.http_dubbo_transcoder.v3', + ] + + BUILD_FILE_TEMPLATE = string.Template( +diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt +index f89846c06b..e1cdf5a94b 100644 +--- a/tools/spelling/spelling_dictionary.txt ++++ b/tools/spelling/spelling_dictionary.txt +@@ -242,6 +242,7 @@ OSI + OSS + OSX + OT ++OTLP + OU + OVFL + PAYLOADLEN +@@ -1200,6 +1201,7 @@ tokenizing + toolchain + traceid + traceparent ++tracestate + transcode + transcoded + transcoder +@@ -1301,3 +1303,6 @@ crlf + ep + suri + transid ++WAF ++TRI ++tmd diff --git a/envoy/1.20/patches/go-control-plane/20221027-init.patch b/envoy/1.20/patches/go-control-plane/20221027-init.patch new file mode 100644 index 000000000..fcfbcce08 --- /dev/null +++ b/envoy/1.20/patches/go-control-plane/20221027-init.patch @@ -0,0 +1,9999 @@ +diff --git a/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.go b/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.go +new file mode 100755 +index 00000000..2fe32ae5 +--- /dev/null ++++ b/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.go +@@ -0,0 +1,374 @@ ++// Code generated by protoc-gen-go. DO NOT EDIT. ++// versions: ++// protoc-gen-go v1.25.0 ++// protoc v3.18.0 ++// source: contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.proto ++ ++package envoy_extensions_custom_cluster_plugins_cluster_fallback_v3 ++ ++import ( ++ _ "github.com/cncf/xds/go/udpa/annotations" ++ _ "github.com/envoyproxy/protoc-gen-validate/validate" ++ proto "github.com/golang/protobuf/proto" ++ protoreflect "google.golang.org/protobuf/reflect/protoreflect" ++ protoimpl "google.golang.org/protobuf/runtime/protoimpl" ++ reflect "reflect" ++ sync "sync" ++) ++ ++const ( ++ // Verify that this generated code is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ++ // Verify that runtime/protoimpl is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ++) ++ ++// This is a compile-time assertion that a sufficiently up-to-date version ++// of the legacy proto package is being used. ++const _ = proto.ProtoPackageIsVersion4 ++ ++type ClusterFallbackConfig struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ // Types that are assignable to ConfigSpecifier: ++ // *ClusterFallbackConfig_ClusterConfig_ ++ // *ClusterFallbackConfig_WeightedClusterConfig_ ++ ConfigSpecifier isClusterFallbackConfig_ConfigSpecifier `protobuf_oneof:"config_specifier"` ++} ++ ++func (x *ClusterFallbackConfig) Reset() { ++ *x = ClusterFallbackConfig{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[0] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *ClusterFallbackConfig) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*ClusterFallbackConfig) ProtoMessage() {} ++ ++func (x *ClusterFallbackConfig) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[0] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use ClusterFallbackConfig.ProtoReflect.Descriptor instead. ++func (*ClusterFallbackConfig) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescGZIP(), []int{0} ++} ++ ++func (m *ClusterFallbackConfig) GetConfigSpecifier() isClusterFallbackConfig_ConfigSpecifier { ++ if m != nil { ++ return m.ConfigSpecifier ++ } ++ return nil ++} ++ ++func (x *ClusterFallbackConfig) GetClusterConfig() *ClusterFallbackConfig_ClusterConfig { ++ if x, ok := x.GetConfigSpecifier().(*ClusterFallbackConfig_ClusterConfig_); ok { ++ return x.ClusterConfig ++ } ++ return nil ++} ++ ++func (x *ClusterFallbackConfig) GetWeightedClusterConfig() *ClusterFallbackConfig_WeightedClusterConfig { ++ if x, ok := x.GetConfigSpecifier().(*ClusterFallbackConfig_WeightedClusterConfig_); ok { ++ return x.WeightedClusterConfig ++ } ++ return nil ++} ++ ++type isClusterFallbackConfig_ConfigSpecifier interface { ++ isClusterFallbackConfig_ConfigSpecifier() ++} ++ ++type ClusterFallbackConfig_ClusterConfig_ struct { ++ ClusterConfig *ClusterFallbackConfig_ClusterConfig `protobuf:"bytes,1,opt,name=cluster_config,json=clusterConfig,proto3,oneof"` ++} ++ ++type ClusterFallbackConfig_WeightedClusterConfig_ struct { ++ WeightedClusterConfig *ClusterFallbackConfig_WeightedClusterConfig `protobuf:"bytes,2,opt,name=weighted_cluster_config,json=weightedClusterConfig,proto3,oneof"` ++} ++ ++func (*ClusterFallbackConfig_ClusterConfig_) isClusterFallbackConfig_ConfigSpecifier() {} ++ ++func (*ClusterFallbackConfig_WeightedClusterConfig_) isClusterFallbackConfig_ConfigSpecifier() {} ++ ++type ClusterFallbackConfig_ClusterConfig struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ RoutingCluster string `protobuf:"bytes,1,opt,name=routing_cluster,json=routingCluster,proto3" json:"routing_cluster,omitempty"` ++ FallbackClusters []string `protobuf:"bytes,2,rep,name=fallback_clusters,json=fallbackClusters,proto3" json:"fallback_clusters,omitempty"` ++} ++ ++func (x *ClusterFallbackConfig_ClusterConfig) Reset() { ++ *x = ClusterFallbackConfig_ClusterConfig{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[1] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *ClusterFallbackConfig_ClusterConfig) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*ClusterFallbackConfig_ClusterConfig) ProtoMessage() {} ++ ++func (x *ClusterFallbackConfig_ClusterConfig) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[1] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use ClusterFallbackConfig_ClusterConfig.ProtoReflect.Descriptor instead. ++func (*ClusterFallbackConfig_ClusterConfig) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescGZIP(), []int{0, 0} ++} ++ ++func (x *ClusterFallbackConfig_ClusterConfig) GetRoutingCluster() string { ++ if x != nil { ++ return x.RoutingCluster ++ } ++ return "" ++} ++ ++func (x *ClusterFallbackConfig_ClusterConfig) GetFallbackClusters() []string { ++ if x != nil { ++ return x.FallbackClusters ++ } ++ return nil ++} ++ ++type ClusterFallbackConfig_WeightedClusterConfig struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ Config []*ClusterFallbackConfig_ClusterConfig `protobuf:"bytes,1,rep,name=config,proto3" json:"config,omitempty"` ++} ++ ++func (x *ClusterFallbackConfig_WeightedClusterConfig) Reset() { ++ *x = ClusterFallbackConfig_WeightedClusterConfig{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[2] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *ClusterFallbackConfig_WeightedClusterConfig) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*ClusterFallbackConfig_WeightedClusterConfig) ProtoMessage() {} ++ ++func (x *ClusterFallbackConfig_WeightedClusterConfig) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[2] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use ClusterFallbackConfig_WeightedClusterConfig.ProtoReflect.Descriptor instead. ++func (*ClusterFallbackConfig_WeightedClusterConfig) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescGZIP(), []int{0, 1} ++} ++ ++func (x *ClusterFallbackConfig_WeightedClusterConfig) GetConfig() []*ClusterFallbackConfig_ClusterConfig { ++ if x != nil { ++ return x.Config ++ } ++ return nil ++} ++ ++var File_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto protoreflect.FileDescriptor ++ ++var file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDesc = []byte{ ++ 0x0a, 0x5a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, ++ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, ++ 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, ++ 0x73, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, ++ 0x63, 0x6b, 0x2f, 0x76, 0x33, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x61, ++ 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x3b, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x63, ++ 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x6c, ++ 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x61, ++ 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x76, 0x33, 0x1a, 0x20, 0x75, 0x64, 0x70, 0x61, 0x2f, ++ 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x65, 0x6e, 0x73, ++ 0x69, 0x74, 0x69, 0x76, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x75, 0x64, 0x70, ++ 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x74, ++ 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, ++ 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x22, 0xd7, 0x04, 0x0a, 0x15, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x46, ++ 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x89, 0x01, ++ 0x0a, 0x0e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x60, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, ++ 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, ++ 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, ++ 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, ++ 0x6b, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x46, 0x61, 0x6c, 0x6c, ++ 0x62, 0x61, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, ++ 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, ++ 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0xa2, 0x01, 0x0a, 0x17, 0x77, 0x65, ++ 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x63, ++ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x68, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x63, ++ 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x6c, ++ 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x61, ++ 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, ++ 0x72, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, ++ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x15, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, ++ 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x65, ++ 0x0a, 0x0d, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, ++ 0x27, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, ++ 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, ++ 0x67, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, ++ 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, ++ 0x03, 0x28, 0x09, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x43, 0x6c, 0x75, ++ 0x73, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x91, 0x01, 0x0a, 0x15, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, ++ 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, ++ 0x78, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, ++ 0x60, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, ++ 0x6e, 0x73, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, ++ 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, ++ 0x72, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, ++ 0x75, 0x73, 0x74, 0x65, 0x72, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x12, 0x0a, 0x10, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x42, 0x6b, 0x0a, ++ 0x49, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, ++ 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, ++ 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, ++ 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x76, 0x33, 0x42, 0x14, 0x43, 0x6c, 0x75, 0x73, ++ 0x74, 0x65, 0x72, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, ++ 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x33, ++} ++ ++var ( ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescOnce sync.Once ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescData = file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDesc ++) ++ ++func file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescGZIP() []byte { ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescOnce.Do(func() { ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescData = protoimpl.X.CompressGZIP(file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescData) ++ }) ++ return file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDescData ++} ++ ++var file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes = make([]protoimpl.MessageInfo, 3) ++var file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_goTypes = []interface{}{ ++ (*ClusterFallbackConfig)(nil), // 0: envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig ++ (*ClusterFallbackConfig_ClusterConfig)(nil), // 1: envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.ClusterConfig ++ (*ClusterFallbackConfig_WeightedClusterConfig)(nil), // 2: envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.WeightedClusterConfig ++} ++var file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_depIdxs = []int32{ ++ 1, // 0: envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.cluster_config:type_name -> envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.ClusterConfig ++ 2, // 1: envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.weighted_cluster_config:type_name -> envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.WeightedClusterConfig ++ 1, // 2: envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.WeightedClusterConfig.config:type_name -> envoy.extensions.custom_cluster_plugins.cluster_fallback.v3.ClusterFallbackConfig.ClusterConfig ++ 3, // [3:3] is the sub-list for method output_type ++ 3, // [3:3] is the sub-list for method input_type ++ 3, // [3:3] is the sub-list for extension type_name ++ 3, // [3:3] is the sub-list for extension extendee ++ 0, // [0:3] is the sub-list for field type_name ++} ++ ++func init() { ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_init() ++} ++func file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_init() { ++ if File_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto != nil { ++ return ++ } ++ if !protoimpl.UnsafeEnabled { ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*ClusterFallbackConfig); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*ClusterFallbackConfig_ClusterConfig); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*ClusterFallbackConfig_WeightedClusterConfig); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ } ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes[0].OneofWrappers = []interface{}{ ++ (*ClusterFallbackConfig_ClusterConfig_)(nil), ++ (*ClusterFallbackConfig_WeightedClusterConfig_)(nil), ++ } ++ type x struct{} ++ out := protoimpl.TypeBuilder{ ++ File: protoimpl.DescBuilder{ ++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), ++ RawDescriptor: file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDesc, ++ NumEnums: 0, ++ NumMessages: 3, ++ NumExtensions: 0, ++ NumServices: 0, ++ }, ++ GoTypes: file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_goTypes, ++ DependencyIndexes: file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_depIdxs, ++ MessageInfos: file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_msgTypes, ++ }.Build() ++ File_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto = out.File ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_rawDesc = nil ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_goTypes = nil ++ file_contrib_envoy_extensions_custom_cluster_plugins_cluster_fallback_v3_cluster_fallback_proto_depIdxs = nil ++} +diff --git a/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.validate.go b/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.validate.go +new file mode 100755 +index 00000000..b764d89b +--- /dev/null ++++ b/contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.pb.validate.go +@@ -0,0 +1,282 @@ ++// Code generated by protoc-gen-validate. DO NOT EDIT. ++// source: contrib/envoy/extensions/custom_cluster_plugins/cluster_fallback/v3/cluster_fallback.proto ++ ++package envoy_extensions_custom_cluster_plugins_cluster_fallback_v3 ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "net" ++ "net/mail" ++ "net/url" ++ "regexp" ++ "strings" ++ "time" ++ "unicode/utf8" ++ ++ "google.golang.org/protobuf/types/known/anypb" ++) ++ ++// ensure the imports are used ++var ( ++ _ = bytes.MinRead ++ _ = errors.New("") ++ _ = fmt.Print ++ _ = utf8.UTFMax ++ _ = (*regexp.Regexp)(nil) ++ _ = (*strings.Reader)(nil) ++ _ = net.IPv4len ++ _ = time.Duration(0) ++ _ = (*url.URL)(nil) ++ _ = (*mail.Address)(nil) ++ _ = anypb.Any{} ++) ++ ++// Validate checks the field values on ClusterFallbackConfig with the rules ++// defined in the proto definition for this message. If any rules are ++// violated, an error is returned. ++func (m *ClusterFallbackConfig) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ switch m.ConfigSpecifier.(type) { ++ ++ case *ClusterFallbackConfig_ClusterConfig_: ++ ++ if v, ok := interface{}(m.GetClusterConfig()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return ClusterFallbackConfigValidationError{ ++ field: "ClusterConfig", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ case *ClusterFallbackConfig_WeightedClusterConfig_: ++ ++ if v, ok := interface{}(m.GetWeightedClusterConfig()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return ClusterFallbackConfigValidationError{ ++ field: "WeightedClusterConfig", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ return nil ++} ++ ++// ClusterFallbackConfigValidationError is the validation error returned by ++// ClusterFallbackConfig.Validate if the designated constraints aren't met. ++type ClusterFallbackConfigValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e ClusterFallbackConfigValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e ClusterFallbackConfigValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e ClusterFallbackConfigValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e ClusterFallbackConfigValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e ClusterFallbackConfigValidationError) ErrorName() string { ++ return "ClusterFallbackConfigValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e ClusterFallbackConfigValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sClusterFallbackConfig.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = ClusterFallbackConfigValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = ClusterFallbackConfigValidationError{} ++ ++// Validate checks the field values on ClusterFallbackConfig_ClusterConfig with ++// the rules defined in the proto definition for this message. If any rules ++// are violated, an error is returned. ++func (m *ClusterFallbackConfig_ClusterConfig) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ // no validation rules for RoutingCluster ++ ++ return nil ++} ++ ++// ClusterFallbackConfig_ClusterConfigValidationError is the validation error ++// returned by ClusterFallbackConfig_ClusterConfig.Validate if the designated ++// constraints aren't met. ++type ClusterFallbackConfig_ClusterConfigValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e ClusterFallbackConfig_ClusterConfigValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e ClusterFallbackConfig_ClusterConfigValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e ClusterFallbackConfig_ClusterConfigValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e ClusterFallbackConfig_ClusterConfigValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e ClusterFallbackConfig_ClusterConfigValidationError) ErrorName() string { ++ return "ClusterFallbackConfig_ClusterConfigValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e ClusterFallbackConfig_ClusterConfigValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sClusterFallbackConfig_ClusterConfig.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = ClusterFallbackConfig_ClusterConfigValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = ClusterFallbackConfig_ClusterConfigValidationError{} ++ ++// Validate checks the field values on ++// ClusterFallbackConfig_WeightedClusterConfig with the rules defined in the ++// proto definition for this message. If any rules are violated, an error is returned. ++func (m *ClusterFallbackConfig_WeightedClusterConfig) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ for idx, item := range m.GetConfig() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return ClusterFallbackConfig_WeightedClusterConfigValidationError{ ++ field: fmt.Sprintf("Config[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ return nil ++} ++ ++// ClusterFallbackConfig_WeightedClusterConfigValidationError is the validation ++// error returned by ClusterFallbackConfig_WeightedClusterConfig.Validate if ++// the designated constraints aren't met. ++type ClusterFallbackConfig_WeightedClusterConfigValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e ClusterFallbackConfig_WeightedClusterConfigValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e ClusterFallbackConfig_WeightedClusterConfigValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e ClusterFallbackConfig_WeightedClusterConfigValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e ClusterFallbackConfig_WeightedClusterConfigValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e ClusterFallbackConfig_WeightedClusterConfigValidationError) ErrorName() string { ++ return "ClusterFallbackConfig_WeightedClusterConfigValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e ClusterFallbackConfig_WeightedClusterConfigValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sClusterFallbackConfig_WeightedClusterConfig.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = ClusterFallbackConfig_WeightedClusterConfigValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = ClusterFallbackConfig_WeightedClusterConfigValidationError{} +diff --git a/contrib/envoy/extensions/filters/common/sentinel/v3/config.pb.go b/contrib/envoy/extensions/filters/common/sentinel/v3/config.pb.go +new file mode 100755 +index 00000000..4b2720c5 +--- /dev/null ++++ b/contrib/envoy/extensions/filters/common/sentinel/v3/config.pb.go +@@ -0,0 +1,238 @@ ++// Code generated by protoc-gen-go. DO NOT EDIT. ++// versions: ++// protoc-gen-go v1.25.0 ++// protoc v3.18.0 ++// source: contrib/envoy/extensions/filters/common/sentinel/v3/config.proto ++ ++package envoy_extensions_filters_common_sentinel_v3 ++ ++import ( ++ _ "github.com/cncf/xds/go/udpa/annotations" ++ _ "github.com/envoyproxy/protoc-gen-validate/validate" ++ proto "github.com/golang/protobuf/proto" ++ protoreflect "google.golang.org/protobuf/reflect/protoreflect" ++ protoimpl "google.golang.org/protobuf/runtime/protoimpl" ++ reflect "reflect" ++ sync "sync" ++) ++ ++const ( ++ // Verify that this generated code is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ++ // Verify that runtime/protoimpl is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ++) ++ ++// This is a compile-time assertion that a sufficiently up-to-date version ++// of the legacy proto package is being used. ++const _ = proto.ProtoPackageIsVersion4 ++ ++// [#protodoc-title: Sentinel] ++// [#comment:next free field: 2] ++// [#next-free-field: 8] ++type CommonConfig struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ AppName string `protobuf:"bytes,1,opt,name=app_name,json=appName,proto3" json:"app_name,omitempty"` ++ AppType uint32 `protobuf:"varint,2,opt,name=app_type,json=appType,proto3" json:"app_type,omitempty"` ++ SystemMetricIntervalMs uint32 `protobuf:"varint,3,opt,name=system_metric_interval_ms,json=systemMetricIntervalMs,proto3" json:"system_metric_interval_ms,omitempty"` ++ UseCommandCenter bool `protobuf:"varint,4,opt,name=use_command_center,json=useCommandCenter,proto3" json:"use_command_center,omitempty"` ++ AhasRegionId string `protobuf:"bytes,5,opt,name=ahas_region_id,json=ahasRegionId,proto3" json:"ahas_region_id,omitempty"` ++ License string `protobuf:"bytes,6,opt,name=license,proto3" json:"license,omitempty"` ++ AppNamespace string `protobuf:"bytes,7,opt,name=app_namespace,json=appNamespace,proto3" json:"app_namespace,omitempty"` ++ LogDir string `protobuf:"bytes,8,opt,name=log_dir,json=logDir,proto3" json:"log_dir,omitempty"` ++} ++ ++func (x *CommonConfig) Reset() { ++ *x = CommonConfig{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_msgTypes[0] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *CommonConfig) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*CommonConfig) ProtoMessage() {} ++ ++func (x *CommonConfig) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_msgTypes[0] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use CommonConfig.ProtoReflect.Descriptor instead. ++func (*CommonConfig) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescGZIP(), []int{0} ++} ++ ++func (x *CommonConfig) GetAppName() string { ++ if x != nil { ++ return x.AppName ++ } ++ return "" ++} ++ ++func (x *CommonConfig) GetAppType() uint32 { ++ if x != nil { ++ return x.AppType ++ } ++ return 0 ++} ++ ++func (x *CommonConfig) GetSystemMetricIntervalMs() uint32 { ++ if x != nil { ++ return x.SystemMetricIntervalMs ++ } ++ return 0 ++} ++ ++func (x *CommonConfig) GetUseCommandCenter() bool { ++ if x != nil { ++ return x.UseCommandCenter ++ } ++ return false ++} ++ ++func (x *CommonConfig) GetAhasRegionId() string { ++ if x != nil { ++ return x.AhasRegionId ++ } ++ return "" ++} ++ ++func (x *CommonConfig) GetLicense() string { ++ if x != nil { ++ return x.License ++ } ++ return "" ++} ++ ++func (x *CommonConfig) GetAppNamespace() string { ++ if x != nil { ++ return x.AppNamespace ++ } ++ return "" ++} ++ ++func (x *CommonConfig) GetLogDir() string { ++ if x != nil { ++ return x.LogDir ++ } ++ return "" ++} ++ ++var File_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto protoreflect.FileDescriptor ++ ++var file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDesc = []byte{ ++ 0x0a, 0x40, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, ++ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x69, 0x6c, 0x74, 0x65, ++ 0x72, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, ++ 0x65, 0x6c, 0x2f, 0x76, 0x33, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x12, 0x2b, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, ++ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x33, 0x1a, ++ 0x1d, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, ++ 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, ++ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, ++ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb4, 0x02, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x6d, ++ 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, ++ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, ++ 0x02, 0x10, 0x01, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, ++ 0x61, 0x70, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, ++ 0x61, 0x70, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x39, 0x0a, 0x19, 0x73, 0x79, 0x73, 0x74, 0x65, ++ 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, ++ 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x73, 0x79, 0x73, 0x74, ++ 0x65, 0x6d, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, ++ 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, ++ 0x64, 0x5f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, ++ 0x75, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, ++ 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x68, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, ++ 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x68, 0x61, 0x73, 0x52, 0x65, ++ 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, ++ 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, ++ 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, ++ 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, ++ 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x5f, 0x64, 0x69, 0x72, ++ 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x67, 0x44, 0x69, 0x72, 0x42, 0x52, ++ 0x0a, 0x39, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, ++ 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, ++ 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x33, 0x42, 0x0b, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, ++ 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++} ++ ++var ( ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescOnce sync.Once ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescData = file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDesc ++) ++ ++func file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescGZIP() []byte { ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescOnce.Do(func() { ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescData) ++ }) ++ return file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDescData ++} ++ ++var file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) ++var file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_goTypes = []interface{}{ ++ (*CommonConfig)(nil), // 0: envoy.extensions.filters.common.sentinel.v3.CommonConfig ++} ++var file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_depIdxs = []int32{ ++ 0, // [0:0] is the sub-list for method output_type ++ 0, // [0:0] is the sub-list for method input_type ++ 0, // [0:0] is the sub-list for extension type_name ++ 0, // [0:0] is the sub-list for extension extendee ++ 0, // [0:0] is the sub-list for field type_name ++} ++ ++func init() { file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_init() } ++func file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_init() { ++ if File_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto != nil { ++ return ++ } ++ if !protoimpl.UnsafeEnabled { ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*CommonConfig); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ } ++ type x struct{} ++ out := protoimpl.TypeBuilder{ ++ File: protoimpl.DescBuilder{ ++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), ++ RawDescriptor: file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDesc, ++ NumEnums: 0, ++ NumMessages: 1, ++ NumExtensions: 0, ++ NumServices: 0, ++ }, ++ GoTypes: file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_goTypes, ++ DependencyIndexes: file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_depIdxs, ++ MessageInfos: file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_msgTypes, ++ }.Build() ++ File_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto = out.File ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_rawDesc = nil ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_goTypes = nil ++ file_contrib_envoy_extensions_filters_common_sentinel_v3_config_proto_depIdxs = nil ++} +diff --git a/contrib/envoy/extensions/filters/common/sentinel/v3/config.pb.validate.go b/contrib/envoy/extensions/filters/common/sentinel/v3/config.pb.validate.go +new file mode 100755 +index 00000000..39ea7415 +--- /dev/null ++++ b/contrib/envoy/extensions/filters/common/sentinel/v3/config.pb.validate.go +@@ -0,0 +1,120 @@ ++// Code generated by protoc-gen-validate. DO NOT EDIT. ++// source: contrib/envoy/extensions/filters/common/sentinel/v3/config.proto ++ ++package envoy_extensions_filters_common_sentinel_v3 ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "net" ++ "net/mail" ++ "net/url" ++ "regexp" ++ "strings" ++ "time" ++ "unicode/utf8" ++ ++ "google.golang.org/protobuf/types/known/anypb" ++) ++ ++// ensure the imports are used ++var ( ++ _ = bytes.MinRead ++ _ = errors.New("") ++ _ = fmt.Print ++ _ = utf8.UTFMax ++ _ = (*regexp.Regexp)(nil) ++ _ = (*strings.Reader)(nil) ++ _ = net.IPv4len ++ _ = time.Duration(0) ++ _ = (*url.URL)(nil) ++ _ = (*mail.Address)(nil) ++ _ = anypb.Any{} ++) ++ ++// Validate checks the field values on CommonConfig with the rules defined in ++// the proto definition for this message. If any rules are violated, an error ++// is returned. ++func (m *CommonConfig) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if utf8.RuneCountInString(m.GetAppName()) < 1 { ++ return CommonConfigValidationError{ ++ field: "AppName", ++ reason: "value length must be at least 1 runes", ++ } ++ } ++ ++ // no validation rules for AppType ++ ++ // no validation rules for SystemMetricIntervalMs ++ ++ // no validation rules for UseCommandCenter ++ ++ // no validation rules for AhasRegionId ++ ++ // no validation rules for License ++ ++ // no validation rules for AppNamespace ++ ++ // no validation rules for LogDir ++ ++ return nil ++} ++ ++// CommonConfigValidationError is the validation error returned by ++// CommonConfig.Validate if the designated constraints aren't met. ++type CommonConfigValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e CommonConfigValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e CommonConfigValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e CommonConfigValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e CommonConfigValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e CommonConfigValidationError) ErrorName() string { return "CommonConfigValidationError" } ++ ++// Error satisfies the builtin error interface ++func (e CommonConfigValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sCommonConfig.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = CommonConfigValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = CommonConfigValidationError{} +diff --git a/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.go b/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.go +new file mode 100755 +index 00000000..be1bbbee +--- /dev/null ++++ b/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.go +@@ -0,0 +1,1065 @@ ++// Code generated by protoc-gen-go. DO NOT EDIT. ++// versions: ++// protoc-gen-go v1.25.0 ++// protoc v3.18.0 ++// source: contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.proto ++ ++package envoy_extensions_filters_http_http_dubbo_transcoder_v3 ++ ++import ( ++ _ "github.com/cncf/xds/go/udpa/annotations" ++ _ "github.com/envoyproxy/protoc-gen-validate/validate" ++ proto "github.com/golang/protobuf/proto" ++ _ "github.com/golang/protobuf/ptypes/wrappers" ++ protoreflect "google.golang.org/protobuf/reflect/protoreflect" ++ protoimpl "google.golang.org/protobuf/runtime/protoimpl" ++ reflect "reflect" ++ sync "sync" ++) ++ ++const ( ++ // Verify that this generated code is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ++ // Verify that runtime/protoimpl is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ++) ++ ++// This is a compile-time assertion that a sufficiently up-to-date version ++// of the legacy proto package is being used. ++const _ = proto.ProtoPackageIsVersion4 ++ ++type HttpDubboTranscoder_UrlUnescapeSpec int32 ++ ++const ( ++ // URL path parameters will not decode RFC 6570 reserved characters. ++ // For example, segment `%2f%23/%20%2523` is unescaped to `%2f%23/ %23`. ++ HttpDubboTranscoder_ALL_CHARACTERS_EXCEPT_RESERVED HttpDubboTranscoder_UrlUnescapeSpec = 0 ++ // URL path parameters will be fully URI-decoded except in ++ // cases of single segment matches in reserved expansion, where "%2F" will be ++ // left encoded. ++ // For example, segment `%2f%23/%20%2523` is unescaped to `%2f#/ %23`. ++ HttpDubboTranscoder_ALL_CHARACTERS_EXCEPT_SLASH HttpDubboTranscoder_UrlUnescapeSpec = 1 ++ // URL path parameters will be fully URI-decoded. ++ // For example, segment `%2f%23/%20%2523` is unescaped to `/#/ %23`. ++ HttpDubboTranscoder_ALL_CHARACTERS HttpDubboTranscoder_UrlUnescapeSpec = 2 ++) ++ ++// Enum value maps for HttpDubboTranscoder_UrlUnescapeSpec. ++var ( ++ HttpDubboTranscoder_UrlUnescapeSpec_name = map[int32]string{ ++ 0: "ALL_CHARACTERS_EXCEPT_RESERVED", ++ 1: "ALL_CHARACTERS_EXCEPT_SLASH", ++ 2: "ALL_CHARACTERS", ++ } ++ HttpDubboTranscoder_UrlUnescapeSpec_value = map[string]int32{ ++ "ALL_CHARACTERS_EXCEPT_RESERVED": 0, ++ "ALL_CHARACTERS_EXCEPT_SLASH": 1, ++ "ALL_CHARACTERS": 2, ++ } ++) ++ ++func (x HttpDubboTranscoder_UrlUnescapeSpec) Enum() *HttpDubboTranscoder_UrlUnescapeSpec { ++ p := new(HttpDubboTranscoder_UrlUnescapeSpec) ++ *p = x ++ return p ++} ++ ++func (x HttpDubboTranscoder_UrlUnescapeSpec) String() string { ++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) ++} ++ ++func (HttpDubboTranscoder_UrlUnescapeSpec) Descriptor() protoreflect.EnumDescriptor { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes[0].Descriptor() ++} ++ ++func (HttpDubboTranscoder_UrlUnescapeSpec) Type() protoreflect.EnumType { ++ return &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes[0] ++} ++ ++func (x HttpDubboTranscoder_UrlUnescapeSpec) Number() protoreflect.EnumNumber { ++ return protoreflect.EnumNumber(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_UrlUnescapeSpec.Descriptor instead. ++func (HttpDubboTranscoder_UrlUnescapeSpec) EnumDescriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 0} ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec int32 ++ ++const ( ++ HttpDubboTranscoder_DubboMethodMapping_ALL_GET HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec = 0 ++ HttpDubboTranscoder_DubboMethodMapping_ALL_POST HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec = 1 ++ HttpDubboTranscoder_DubboMethodMapping_ALL_PUT HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec = 2 ++ HttpDubboTranscoder_DubboMethodMapping_ALL_DELETE HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec = 3 ++ HttpDubboTranscoder_DubboMethodMapping_ALL_PATCH HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec = 4 ++) ++ ++// Enum value maps for HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec. ++var ( ++ HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec_name = map[int32]string{ ++ 0: "ALL_GET", ++ 1: "ALL_POST", ++ 2: "ALL_PUT", ++ 3: "ALL_DELETE", ++ 4: "ALL_PATCH", ++ } ++ HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec_value = map[string]int32{ ++ "ALL_GET": 0, ++ "ALL_POST": 1, ++ "ALL_PUT": 2, ++ "ALL_DELETE": 3, ++ "ALL_PATCH": 4, ++ } ++) ++ ++func (x HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec) Enum() *HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec { ++ p := new(HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec) ++ *p = x ++ return p ++} ++ ++func (x HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec) String() string { ++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) ++} ++ ++func (HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec) Descriptor() protoreflect.EnumDescriptor { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes[1].Descriptor() ++} ++ ++func (HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec) Type() protoreflect.EnumType { ++ return &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes[1] ++} ++ ++func (x HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec) Number() protoreflect.EnumNumber { ++ return protoreflect.EnumNumber(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec.Descriptor instead. ++func (HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec) EnumDescriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 1, 0} ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec int32 ++ ++const ( ++ HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ALL_QUERY_PARAMETER HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec = 0 ++ HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ALL_HEADER HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec = 1 ++ HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ALL_PATH HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec = 2 ++ HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ALL_BODY HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec = 3 ++) ++ ++// Enum value maps for HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec. ++var ( ++ HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec_name = map[int32]string{ ++ 0: "ALL_QUERY_PARAMETER", ++ 1: "ALL_HEADER", ++ 2: "ALL_PATH", ++ 3: "ALL_BODY", ++ } ++ HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec_value = map[string]int32{ ++ "ALL_QUERY_PARAMETER": 0, ++ "ALL_HEADER": 1, ++ "ALL_PATH": 2, ++ "ALL_BODY": 3, ++ } ++) ++ ++func (x HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec) Enum() *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec { ++ p := new(HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec) ++ *p = x ++ return p ++} ++ ++func (x HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec) String() string { ++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) ++} ++ ++func (HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec) Descriptor() protoreflect.EnumDescriptor { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes[2].Descriptor() ++} ++ ++func (HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec) Type() protoreflect.EnumType { ++ return &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes[2] ++} ++ ++func (x HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec) Number() protoreflect.EnumNumber { ++ return protoreflect.EnumNumber(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec.Descriptor instead. ++func (HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec) EnumDescriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 1, 0, 0} ++} ++ ++// [#protodoc-title: Buffer] ++// Buffer :ref:`configuration overview `. ++// [#extension: envoy.filters.http.buffer] ++type HttpDubboTranscoder struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ // Configure the behavior when handling requests that cannot be transcoded. ++ // ++ // By default, the transcoder will silently pass through HTTP requests that are malformed. ++ // This includes requests with unknown query parameters, unregister paths, etc. ++ RequestValidationOptions *HttpDubboTranscoder_RequestValidateOptions `protobuf:"bytes,2,opt,name=request_validation_options,json=requestValidationOptions,proto3" json:"request_validation_options,omitempty"` ++ // URL unescaping policy. ++ // This spec is only applied when extracting variable with multiple segments in the URL path. ++ // For example, in case of `/foo/{x=*}/bar/{y=prefix/*}/{z=**}` `x` variable is single segment and `y` and `z` are multiple segments. ++ // For a path with `/foo/first/bar/prefix/second/third/fourth`, `x=first`, `y=prefix/second`, `z=third/fourth`. ++ // If this setting is not specified, the value defaults to :ref:`ALL_CHARACTERS_EXCEPT_RESERVED`. ++ UrlUnescapeSpec HttpDubboTranscoder_UrlUnescapeSpec `protobuf:"varint,3,opt,name=url_unescape_spec,json=urlUnescapeSpec,proto3,enum=envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder_UrlUnescapeSpec" json:"url_unescape_spec,omitempty"` ++ ServicesMapping []*HttpDubboTranscoder_DubboServiceMapping `protobuf:"bytes,4,rep,name=services_mapping,json=servicesMapping,proto3" json:"services_mapping,omitempty"` ++} ++ ++func (x *HttpDubboTranscoder) Reset() { ++ *x = HttpDubboTranscoder{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[0] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[0] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0} ++} ++ ++func (x *HttpDubboTranscoder) GetRequestValidationOptions() *HttpDubboTranscoder_RequestValidateOptions { ++ if x != nil { ++ return x.RequestValidationOptions ++ } ++ return nil ++} ++ ++func (x *HttpDubboTranscoder) GetUrlUnescapeSpec() HttpDubboTranscoder_UrlUnescapeSpec { ++ if x != nil { ++ return x.UrlUnescapeSpec ++ } ++ return HttpDubboTranscoder_ALL_CHARACTERS_EXCEPT_RESERVED ++} ++ ++func (x *HttpDubboTranscoder) GetServicesMapping() []*HttpDubboTranscoder_DubboServiceMapping { ++ if x != nil { ++ return x.ServicesMapping ++ } ++ return nil ++} ++ ++type HttpDubboTranscoder_RequestValidateOptions struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ // default this trascoder will pass the request which contains unknown query paramters, ++ // if this option set to true, the request will be reject with 400 Bad Request. ++ RejectUnknownQueryParameters bool `protobuf:"varint,1,opt,name=reject_unknown_query_parameters,json=rejectUnknownQueryParameters,proto3" json:"reject_unknown_query_parameters,omitempty"` ++ RejectUnknownMethod bool `protobuf:"varint,2,opt,name=reject_unknown_method,json=rejectUnknownMethod,proto3" json:"reject_unknown_method,omitempty"` ++} ++ ++func (x *HttpDubboTranscoder_RequestValidateOptions) Reset() { ++ *x = HttpDubboTranscoder_RequestValidateOptions{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[1] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder_RequestValidateOptions) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder_RequestValidateOptions) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder_RequestValidateOptions) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[1] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_RequestValidateOptions.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder_RequestValidateOptions) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 0} ++} ++ ++func (x *HttpDubboTranscoder_RequestValidateOptions) GetRejectUnknownQueryParameters() bool { ++ if x != nil { ++ return x.RejectUnknownQueryParameters ++ } ++ return false ++} ++ ++func (x *HttpDubboTranscoder_RequestValidateOptions) GetRejectUnknownMethod() bool { ++ if x != nil { ++ return x.RejectUnknownMethod ++ } ++ return false ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` ++ PathMatcher *HttpDubboTranscoder_DubboMethodMapping_PathMatcher `protobuf:"bytes,2,opt,name=path_matcher,json=pathMatcher,proto3" json:"path_matcher,omitempty"` ++ ParameterMapping []*HttpDubboTranscoder_DubboMethodMapping_ParameterMapping `protobuf:"bytes,3,rep,name=parameter_mapping,json=parameterMapping,proto3" json:"parameter_mapping,omitempty"` ++ PassthroughSetting *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting `protobuf:"bytes,4,opt,name=passthrough_setting,json=passthroughSetting,proto3" json:"passthrough_setting,omitempty"` ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping) Reset() { ++ *x = HttpDubboTranscoder_DubboMethodMapping{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[2] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder_DubboMethodMapping) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[2] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboMethodMapping.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder_DubboMethodMapping) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 1} ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping) GetName() string { ++ if x != nil { ++ return x.Name ++ } ++ return "" ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping) GetPathMatcher() *HttpDubboTranscoder_DubboMethodMapping_PathMatcher { ++ if x != nil { ++ return x.PathMatcher ++ } ++ return nil ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping) GetParameterMapping() []*HttpDubboTranscoder_DubboMethodMapping_ParameterMapping { ++ if x != nil { ++ return x.ParameterMapping ++ } ++ return nil ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping) GetPassthroughSetting() *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting { ++ if x != nil { ++ return x.PassthroughSetting ++ } ++ return nil ++} ++ ++type HttpDubboTranscoder_DubboServiceMapping struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` ++ Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` ++ MethodMapping []*HttpDubboTranscoder_DubboMethodMapping `protobuf:"bytes,3,rep,name=method_mapping,json=methodMapping,proto3" json:"method_mapping,omitempty"` ++} ++ ++func (x *HttpDubboTranscoder_DubboServiceMapping) Reset() { ++ *x = HttpDubboTranscoder_DubboServiceMapping{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[3] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder_DubboServiceMapping) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder_DubboServiceMapping) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder_DubboServiceMapping) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[3] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboServiceMapping.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder_DubboServiceMapping) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 2} ++} ++ ++func (x *HttpDubboTranscoder_DubboServiceMapping) GetName() string { ++ if x != nil { ++ return x.Name ++ } ++ return "" ++} ++ ++func (x *HttpDubboTranscoder_DubboServiceMapping) GetVersion() string { ++ if x != nil { ++ return x.Version ++ } ++ return "" ++} ++ ++func (x *HttpDubboTranscoder_DubboServiceMapping) GetMethodMapping() []*HttpDubboTranscoder_DubboMethodMapping { ++ if x != nil { ++ return x.MethodMapping ++ } ++ return nil ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_ParameterMapping struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ ExtractKeySpec HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec `protobuf:"varint,1,opt,name=extract_key_spec,json=extractKeySpec,proto3,enum=envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec" json:"extract_key_spec,omitempty"` ++ ExtractKey string `protobuf:"bytes,2,opt,name=extract_key,json=extractKey,proto3" json:"extract_key,omitempty"` ++ MappingType string `protobuf:"bytes,3,opt,name=mapping_type,json=mappingType,proto3" json:"mapping_type,omitempty"` ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) Reset() { ++ *x = HttpDubboTranscoder_DubboMethodMapping_ParameterMapping{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[4] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[4] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboMethodMapping_ParameterMapping.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 1, 0} ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) GetExtractKeySpec() HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec { ++ if x != nil { ++ return x.ExtractKeySpec ++ } ++ return HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ALL_QUERY_PARAMETER ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) GetExtractKey() string { ++ if x != nil { ++ return x.ExtractKey ++ } ++ return "" ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) GetMappingType() string { ++ if x != nil { ++ return x.MappingType ++ } ++ return "" ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_PathMatcher struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ MatchPattern string `protobuf:"bytes,1,opt,name=match_pattern,json=matchPattern,proto3" json:"match_pattern,omitempty"` ++ MatchHttpMethodSpec HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec `protobuf:"varint,2,opt,name=match_http_method_spec,json=matchHttpMethodSpec,proto3,enum=envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec" json:"match_http_method_spec,omitempty"` ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PathMatcher) Reset() { ++ *x = HttpDubboTranscoder_DubboMethodMapping_PathMatcher{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[5] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PathMatcher) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder_DubboMethodMapping_PathMatcher) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PathMatcher) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[5] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboMethodMapping_PathMatcher.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder_DubboMethodMapping_PathMatcher) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 1, 1} ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PathMatcher) GetMatchPattern() string { ++ if x != nil { ++ return x.MatchPattern ++ } ++ return "" ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PathMatcher) GetMatchHttpMethodSpec() HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec { ++ if x != nil { ++ return x.MatchHttpMethodSpec ++ } ++ return HttpDubboTranscoder_DubboMethodMapping_ALL_GET ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ // Types that are assignable to HeadersSetting: ++ // *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughAllHeaders ++ // *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders_ ++ HeadersSetting isHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_HeadersSetting `protobuf_oneof:"headers_setting"` ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) Reset() { ++ *x = HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[6] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[6] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 1, 2} ++} ++ ++func (m *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) GetHeadersSetting() isHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_HeadersSetting { ++ if m != nil { ++ return m.HeadersSetting ++ } ++ return nil ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) GetPassthroughAllHeaders() bool { ++ if x, ok := x.GetHeadersSetting().(*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughAllHeaders); ok { ++ return x.PassthroughAllHeaders ++ } ++ return false ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) GetPassthroughHeaders() *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders { ++ if x, ok := x.GetHeadersSetting().(*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders_); ok { ++ return x.PassthroughHeaders ++ } ++ return nil ++} ++ ++type isHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_HeadersSetting interface { ++ isHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_HeadersSetting() ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughAllHeaders struct { ++ PassthroughAllHeaders bool `protobuf:"varint,1,opt,name=passthrough_all_headers,json=passthroughAllHeaders,proto3,oneof"` ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders_ struct { ++ PassthroughHeaders *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders `protobuf:"bytes,2,opt,name=passthrough_headers,json=passthroughHeaders,proto3,oneof"` ++} ++ ++func (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughAllHeaders) isHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_HeadersSetting() { ++} ++ ++func (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders_) isHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_HeadersSetting() { ++} ++ ++type HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ Keys []string `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"` ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders) Reset() { ++ *x = HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[7] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders) ProtoMessage() {} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[7] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders.ProtoReflect.Descriptor instead. ++func (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP(), []int{0, 1, 2, 0} ++} ++ ++func (x *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders) GetKeys() []string { ++ if x != nil { ++ return x.Keys ++ } ++ return nil ++} ++ ++var File_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto protoreflect.FileDescriptor ++ ++var file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDesc = []byte{ ++ 0x0a, 0x5a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, ++ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x69, 0x6c, 0x74, 0x65, ++ 0x72, 0x73, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, 0x75, 0x62, ++ 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x33, ++ 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, ++ 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x36, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, ++ 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, ++ 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, ++ 0x72, 0x2e, 0x76, 0x33, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, ++ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, ++ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, ++ 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, ++ 0xa4, 0x13, 0x0a, 0x13, 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, ++ 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x12, 0xa0, 0x01, 0x0a, 0x1a, 0x72, 0x65, 0x71, 0x75, ++ 0x65, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x62, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, ++ 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, ++ 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, ++ 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, ++ 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, ++ 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, ++ 0x52, 0x18, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, ++ 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x91, 0x01, 0x0a, 0x11, 0x75, ++ 0x72, 0x6c, 0x5f, 0x75, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, ++ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x5b, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, ++ 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, ++ 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, ++ 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, ++ 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, ++ 0x64, 0x65, 0x72, 0x2e, 0x55, 0x72, 0x6c, 0x55, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x53, ++ 0x70, 0x65, 0x63, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x75, ++ 0x72, 0x6c, 0x55, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x8a, ++ 0x01, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x70, ++ 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x5f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, ++ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, ++ 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, ++ 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, 0x6e, ++ 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x53, 0x65, 0x72, 0x76, ++ 0x69, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, ++ 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x1a, 0x93, 0x01, 0x0a, 0x16, ++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4f, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x1f, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, ++ 0x5f, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x70, ++ 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, ++ 0x1c, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x51, 0x75, ++ 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, ++ 0x15, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, ++ 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x72, 0x65, ++ 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, ++ 0x64, 0x1a, 0xe6, 0x0b, 0x0a, 0x12, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x4d, 0x65, 0x74, 0x68, 0x6f, ++ 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, ++ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6d, ++ 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x6a, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, ++ 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, ++ 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, ++ 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, ++ 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x4d, ++ 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x74, ++ 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x0b, 0x70, 0x61, 0x74, 0x68, 0x4d, 0x61, ++ 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x9c, 0x01, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, ++ 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, 0x28, ++ 0x0b, 0x32, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, ++ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, ++ 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, ++ 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x44, ++ 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x44, ++ 0x75, 0x62, 0x62, 0x6f, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, ++ 0x67, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x70, 0x69, ++ 0x6e, 0x67, 0x52, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x70, ++ 0x70, 0x69, 0x6e, 0x67, 0x12, 0xa2, 0x01, 0x0a, 0x13, 0x70, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, ++ 0x6f, 0x75, 0x67, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x71, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, ++ 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, ++ 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, ++ 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, ++ 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, ++ 0x44, 0x75, 0x62, 0x62, 0x6f, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, ++ 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x53, 0x65, ++ 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x12, 0x70, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, ++ 0x67, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0xd8, 0x02, 0x0a, 0x10, 0x50, 0x61, ++ 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0xa8, ++ 0x01, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, ++ 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x7e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, ++ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, ++ 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, ++ 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, 0x6e, ++ 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x4d, 0x65, 0x74, 0x68, ++ 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, ++ 0x74, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, ++ 0x63, 0x74, 0x4b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, ++ 0x63, 0x74, 0x4b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, ++ 0x72, 0x61, 0x63, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, ++ 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, ++ 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, ++ 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0x55, 0x0a, ++ 0x0e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x4b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, ++ 0x17, 0x0a, 0x13, 0x41, 0x4c, 0x4c, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, 0x41, 0x52, ++ 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x4c, 0x4c, 0x5f, ++ 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4c, 0x4c, 0x5f, ++ 0x50, 0x41, 0x54, 0x48, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4c, 0x4c, 0x5f, 0x42, 0x4f, ++ 0x44, 0x59, 0x10, 0x03, 0x1a, 0xdc, 0x01, 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, ++ 0x63, 0x68, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x61, ++ 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x74, ++ 0x63, 0x68, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0xa7, 0x01, 0x0a, 0x16, 0x6d, 0x61, ++ 0x74, 0x63, 0x68, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, ++ 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x72, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, ++ 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, ++ 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, ++ 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, ++ 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x4d, 0x65, 0x74, ++ 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, ++ 0x48, 0x74, 0x74, 0x70, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x70, 0x65, 0x63, 0x52, 0x13, ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x48, 0x74, 0x74, 0x70, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, ++ 0x70, 0x65, 0x63, 0x1a, 0xc6, 0x02, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, ++ 0x75, 0x67, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x38, 0x0a, 0x17, 0x70, 0x61, ++ 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x68, 0x65, ++ 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x15, 0x70, ++ 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x41, 0x6c, 0x6c, 0x48, 0x65, 0x61, ++ 0x64, 0x65, 0x72, 0x73, 0x12, 0xb8, 0x01, 0x0a, 0x13, 0x70, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, ++ 0x6f, 0x75, 0x67, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x84, 0x01, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, ++ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, ++ 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, ++ 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, ++ 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, ++ 0x2e, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, ++ 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x53, ++ 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, ++ 0x67, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x12, 0x70, 0x61, 0x73, ++ 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, ++ 0x28, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x48, 0x65, ++ 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, ++ 0x03, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x42, 0x11, 0x0a, 0x0f, 0x68, 0x65, 0x61, ++ 0x64, 0x65, 0x72, 0x73, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x5c, 0x0a, 0x13, ++ 0x4d, 0x61, 0x74, 0x63, 0x68, 0x48, 0x74, 0x74, 0x70, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, ++ 0x70, 0x65, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4c, 0x4c, 0x5f, 0x47, 0x45, 0x54, 0x10, 0x00, ++ 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4c, 0x4c, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0b, ++ 0x0a, 0x07, 0x41, 0x4c, 0x4c, 0x5f, 0x50, 0x55, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x41, ++ 0x4c, 0x4c, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x41, ++ 0x4c, 0x4c, 0x5f, 0x50, 0x41, 0x54, 0x43, 0x48, 0x10, 0x04, 0x1a, 0xdd, 0x01, 0x0a, 0x13, 0x44, ++ 0x75, 0x62, 0x62, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, ++ 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, ++ 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, ++ 0x21, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, ++ 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, ++ 0x6f, 0x6e, 0x12, 0x85, 0x01, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6d, 0x61, ++ 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x5e, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, ++ 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, ++ 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, ++ 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, ++ 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x4d, 0x65, ++ 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x6d, 0x65, 0x74, ++ 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x22, 0x6a, 0x0a, 0x0f, 0x55, 0x72, ++ 0x6c, 0x55, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x22, 0x0a, ++ 0x1e, 0x41, 0x4c, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x52, 0x41, 0x43, 0x54, 0x45, 0x52, 0x53, 0x5f, ++ 0x45, 0x58, 0x43, 0x45, 0x50, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, ++ 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x4c, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x52, 0x41, 0x43, 0x54, ++ 0x45, 0x52, 0x53, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x50, 0x54, 0x5f, 0x53, 0x4c, 0x41, 0x53, 0x48, ++ 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x4c, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x52, 0x41, 0x43, ++ 0x54, 0x45, 0x52, 0x53, 0x10, 0x02, 0x42, 0x6a, 0x0a, 0x44, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, ++ 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, ++ 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x64, 0x75, 0x62, 0x62, 0x6f, ++ 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x42, 0x18, ++ 0x48, 0x74, 0x74, 0x70, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, ++ 0x64, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, ++ 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++} ++ ++var ( ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescOnce sync.Once ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescData = file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDesc ++) ++ ++func file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescGZIP() []byte { ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescOnce.Do(func() { ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescData = protoimpl.X.CompressGZIP(file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescData) ++ }) ++ return file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDescData ++} ++ ++var file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes = make([]protoimpl.EnumInfo, 3) ++var file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes = make([]protoimpl.MessageInfo, 8) ++var file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_goTypes = []interface{}{ ++ (HttpDubboTranscoder_UrlUnescapeSpec)(0), // 0: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.UrlUnescapeSpec ++ (HttpDubboTranscoder_DubboMethodMapping_MatchHttpMethodSpec)(0), // 1: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.MatchHttpMethodSpec ++ (HttpDubboTranscoder_DubboMethodMapping_ParameterMapping_ExtractKeySpec)(0), // 2: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.ParameterMapping.ExtractKeySpec ++ (*HttpDubboTranscoder)(nil), // 3: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder ++ (*HttpDubboTranscoder_RequestValidateOptions)(nil), // 4: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.RequestValidateOptions ++ (*HttpDubboTranscoder_DubboMethodMapping)(nil), // 5: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping ++ (*HttpDubboTranscoder_DubboServiceMapping)(nil), // 6: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboServiceMapping ++ (*HttpDubboTranscoder_DubboMethodMapping_ParameterMapping)(nil), // 7: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.ParameterMapping ++ (*HttpDubboTranscoder_DubboMethodMapping_PathMatcher)(nil), // 8: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PathMatcher ++ (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting)(nil), // 9: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PassthroughSetting ++ (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders)(nil), // 10: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PassthroughSetting.PassthroughHeaders ++} ++var file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_depIdxs = []int32{ ++ 4, // 0: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.request_validation_options:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.RequestValidateOptions ++ 0, // 1: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.url_unescape_spec:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.UrlUnescapeSpec ++ 6, // 2: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.services_mapping:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboServiceMapping ++ 8, // 3: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.path_matcher:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PathMatcher ++ 7, // 4: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.parameter_mapping:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.ParameterMapping ++ 9, // 5: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.passthrough_setting:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PassthroughSetting ++ 5, // 6: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboServiceMapping.method_mapping:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping ++ 2, // 7: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.ParameterMapping.extract_key_spec:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.ParameterMapping.ExtractKeySpec ++ 1, // 8: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PathMatcher.match_http_method_spec:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.MatchHttpMethodSpec ++ 10, // 9: envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PassthroughSetting.passthrough_headers:type_name -> envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder.DubboMethodMapping.PassthroughSetting.PassthroughHeaders ++ 10, // [10:10] is the sub-list for method output_type ++ 10, // [10:10] is the sub-list for method input_type ++ 10, // [10:10] is the sub-list for extension type_name ++ 10, // [10:10] is the sub-list for extension extendee ++ 0, // [0:10] is the sub-list for field type_name ++} ++ ++func init() { ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_init() ++} ++func file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_init() { ++ if File_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto != nil { ++ return ++ } ++ if !protoimpl.UnsafeEnabled { ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder_RequestValidateOptions); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder_DubboMethodMapping); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder_DubboServiceMapping); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder_DubboMethodMapping_ParameterMapping); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder_DubboMethodMapping_PathMatcher); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ } ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes[6].OneofWrappers = []interface{}{ ++ (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughAllHeaders)(nil), ++ (*HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders_)(nil), ++ } ++ type x struct{} ++ out := protoimpl.TypeBuilder{ ++ File: protoimpl.DescBuilder{ ++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), ++ RawDescriptor: file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDesc, ++ NumEnums: 3, ++ NumMessages: 8, ++ NumExtensions: 0, ++ NumServices: 0, ++ }, ++ GoTypes: file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_goTypes, ++ DependencyIndexes: file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_depIdxs, ++ EnumInfos: file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_enumTypes, ++ MessageInfos: file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_msgTypes, ++ }.Build() ++ File_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto = out.File ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_rawDesc = nil ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_goTypes = nil ++ file_contrib_envoy_extensions_filters_http_http_dubbo_transcoder_v3_http_dubbo_transcoder_proto_depIdxs = nil ++} +diff --git a/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.go b/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.go +new file mode 100755 +index 00000000..c0870dba +--- /dev/null ++++ b/contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.pb.validate.go +@@ -0,0 +1,751 @@ ++// Code generated by protoc-gen-validate. DO NOT EDIT. ++// source: contrib/envoy/extensions/filters/http/http_dubbo_transcoder/v3/http_dubbo_transcoder.proto ++ ++package envoy_extensions_filters_http_http_dubbo_transcoder_v3 ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "net" ++ "net/mail" ++ "net/url" ++ "regexp" ++ "strings" ++ "time" ++ "unicode/utf8" ++ ++ "google.golang.org/protobuf/types/known/anypb" ++) ++ ++// ensure the imports are used ++var ( ++ _ = bytes.MinRead ++ _ = errors.New("") ++ _ = fmt.Print ++ _ = utf8.UTFMax ++ _ = (*regexp.Regexp)(nil) ++ _ = (*strings.Reader)(nil) ++ _ = net.IPv4len ++ _ = time.Duration(0) ++ _ = (*url.URL)(nil) ++ _ = (*mail.Address)(nil) ++ _ = anypb.Any{} ++) ++ ++// Validate checks the field values on HttpDubboTranscoder with the rules ++// defined in the proto definition for this message. If any rules are ++// violated, an error is returned. ++func (m *HttpDubboTranscoder) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if v, ok := interface{}(m.GetRequestValidationOptions()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return HttpDubboTranscoderValidationError{ ++ field: "RequestValidationOptions", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ if _, ok := HttpDubboTranscoder_UrlUnescapeSpec_name[int32(m.GetUrlUnescapeSpec())]; !ok { ++ return HttpDubboTranscoderValidationError{ ++ field: "UrlUnescapeSpec", ++ reason: "value must be one of the defined enum values", ++ } ++ } ++ ++ for idx, item := range m.GetServicesMapping() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return HttpDubboTranscoderValidationError{ ++ field: fmt.Sprintf("ServicesMapping[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ return nil ++} ++ ++// HttpDubboTranscoderValidationError is the validation error returned by ++// HttpDubboTranscoder.Validate if the designated constraints aren't met. ++type HttpDubboTranscoderValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoderValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoderValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoderValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e HttpDubboTranscoderValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoderValidationError) ErrorName() string { ++ return "HttpDubboTranscoderValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoderValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoderValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoderValidationError{} ++ ++// Validate checks the field values on ++// HttpDubboTranscoder_RequestValidateOptions with the rules defined in the ++// proto definition for this message. If any rules are violated, an error is returned. ++func (m *HttpDubboTranscoder_RequestValidateOptions) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ // no validation rules for RejectUnknownQueryParameters ++ ++ // no validation rules for RejectUnknownMethod ++ ++ return nil ++} ++ ++// HttpDubboTranscoder_RequestValidateOptionsValidationError is the validation ++// error returned by HttpDubboTranscoder_RequestValidateOptions.Validate if ++// the designated constraints aren't met. ++type HttpDubboTranscoder_RequestValidateOptionsValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoder_RequestValidateOptionsValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoder_RequestValidateOptionsValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoder_RequestValidateOptionsValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e HttpDubboTranscoder_RequestValidateOptionsValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoder_RequestValidateOptionsValidationError) ErrorName() string { ++ return "HttpDubboTranscoder_RequestValidateOptionsValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoder_RequestValidateOptionsValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder_RequestValidateOptions.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoder_RequestValidateOptionsValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoder_RequestValidateOptionsValidationError{} ++ ++// Validate checks the field values on HttpDubboTranscoder_DubboMethodMapping ++// with the rules defined in the proto definition for this message. If any ++// rules are violated, an error is returned. ++func (m *HttpDubboTranscoder_DubboMethodMapping) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if utf8.RuneCountInString(m.GetName()) < 1 { ++ return HttpDubboTranscoder_DubboMethodMappingValidationError{ ++ field: "Name", ++ reason: "value length must be at least 1 runes", ++ } ++ } ++ ++ if v, ok := interface{}(m.GetPathMatcher()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return HttpDubboTranscoder_DubboMethodMappingValidationError{ ++ field: "PathMatcher", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ for idx, item := range m.GetParameterMapping() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return HttpDubboTranscoder_DubboMethodMappingValidationError{ ++ field: fmt.Sprintf("ParameterMapping[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ if v, ok := interface{}(m.GetPassthroughSetting()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return HttpDubboTranscoder_DubboMethodMappingValidationError{ ++ field: "PassthroughSetting", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ return nil ++} ++ ++// HttpDubboTranscoder_DubboMethodMappingValidationError is the validation ++// error returned by HttpDubboTranscoder_DubboMethodMapping.Validate if the ++// designated constraints aren't met. ++type HttpDubboTranscoder_DubboMethodMappingValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoder_DubboMethodMappingValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoder_DubboMethodMappingValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoder_DubboMethodMappingValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e HttpDubboTranscoder_DubboMethodMappingValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoder_DubboMethodMappingValidationError) ErrorName() string { ++ return "HttpDubboTranscoder_DubboMethodMappingValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoder_DubboMethodMappingValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder_DubboMethodMapping.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoder_DubboMethodMappingValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoder_DubboMethodMappingValidationError{} ++ ++// Validate checks the field values on HttpDubboTranscoder_DubboServiceMapping ++// with the rules defined in the proto definition for this message. If any ++// rules are violated, an error is returned. ++func (m *HttpDubboTranscoder_DubboServiceMapping) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if utf8.RuneCountInString(m.GetName()) < 1 { ++ return HttpDubboTranscoder_DubboServiceMappingValidationError{ ++ field: "Name", ++ reason: "value length must be at least 1 runes", ++ } ++ } ++ ++ if utf8.RuneCountInString(m.GetVersion()) < 1 { ++ return HttpDubboTranscoder_DubboServiceMappingValidationError{ ++ field: "Version", ++ reason: "value length must be at least 1 runes", ++ } ++ } ++ ++ for idx, item := range m.GetMethodMapping() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return HttpDubboTranscoder_DubboServiceMappingValidationError{ ++ field: fmt.Sprintf("MethodMapping[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ return nil ++} ++ ++// HttpDubboTranscoder_DubboServiceMappingValidationError is the validation ++// error returned by HttpDubboTranscoder_DubboServiceMapping.Validate if the ++// designated constraints aren't met. ++type HttpDubboTranscoder_DubboServiceMappingValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoder_DubboServiceMappingValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoder_DubboServiceMappingValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoder_DubboServiceMappingValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e HttpDubboTranscoder_DubboServiceMappingValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoder_DubboServiceMappingValidationError) ErrorName() string { ++ return "HttpDubboTranscoder_DubboServiceMappingValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoder_DubboServiceMappingValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder_DubboServiceMapping.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoder_DubboServiceMappingValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoder_DubboServiceMappingValidationError{} ++ ++// Validate checks the field values on ++// HttpDubboTranscoder_DubboMethodMapping_ParameterMapping with the rules ++// defined in the proto definition for this message. If any rules are ++// violated, an error is returned. ++func (m *HttpDubboTranscoder_DubboMethodMapping_ParameterMapping) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ // no validation rules for ExtractKeySpec ++ ++ // no validation rules for ExtractKey ++ ++ // no validation rules for MappingType ++ ++ return nil ++} ++ ++// HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError is ++// the validation error returned by ++// HttpDubboTranscoder_DubboMethodMapping_ParameterMapping.Validate if the ++// designated constraints aren't met. ++type HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError) Field() string { ++ return e.field ++} ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError) Reason() string { ++ return e.reason ++} ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError) Cause() error { ++ return e.cause ++} ++ ++// Key function returns key value. ++func (e HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError) Key() bool { ++ return e.key ++} ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError) ErrorName() string { ++ return "HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder_DubboMethodMapping_ParameterMapping.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoder_DubboMethodMapping_ParameterMappingValidationError{} ++ ++// Validate checks the field values on ++// HttpDubboTranscoder_DubboMethodMapping_PathMatcher with the rules defined ++// in the proto definition for this message. If any rules are violated, an ++// error is returned. ++func (m *HttpDubboTranscoder_DubboMethodMapping_PathMatcher) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ // no validation rules for MatchPattern ++ ++ // no validation rules for MatchHttpMethodSpec ++ ++ return nil ++} ++ ++// HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError is the ++// validation error returned by ++// HttpDubboTranscoder_DubboMethodMapping_PathMatcher.Validate if the ++// designated constraints aren't met. ++type HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError) Field() string { ++ return e.field ++} ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError) Reason() string { ++ return e.reason ++} ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError) Cause() error { ++ return e.cause ++} ++ ++// Key function returns key value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError) ErrorName() string { ++ return "HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder_DubboMethodMapping_PathMatcher.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoder_DubboMethodMapping_PathMatcherValidationError{} ++ ++// Validate checks the field values on ++// HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting with the rules ++// defined in the proto definition for this message. If any rules are ++// violated, an error is returned. ++func (m *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ switch m.HeadersSetting.(type) { ++ ++ case *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughAllHeaders: ++ // no validation rules for PassthroughAllHeaders ++ ++ case *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders_: ++ ++ if v, ok := interface{}(m.GetPassthroughHeaders()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError{ ++ field: "PassthroughHeaders", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ return nil ++} ++ ++// HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError is ++// the validation error returned by ++// HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting.Validate if the ++// designated constraints aren't met. ++type HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError) Field() string { ++ return e.field ++} ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError) Reason() string { ++ return e.reason ++} ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError) Cause() error { ++ return e.cause ++} ++ ++// Key function returns key value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError) Key() bool { ++ return e.key ++} ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError) ErrorName() string { ++ return "HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoder_DubboMethodMapping_PassthroughSettingValidationError{} ++ ++// Validate checks the field values on ++// HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders ++// with the rules defined in the proto definition for this message. If any ++// rules are violated, an error is returned. ++func (m *HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ return nil ++} ++ ++// HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError ++// is the validation error returned by ++// HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders.Validate ++// if the designated constraints aren't met. ++type HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError) Field() string { ++ return e.field ++} ++ ++// Reason function returns reason value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError) Reason() string { ++ return e.reason ++} ++ ++// Cause function returns cause value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError) Cause() error { ++ return e.cause ++} ++ ++// Key function returns key value. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError) Key() bool { ++ return e.key ++} ++ ++// ErrorName returns error name. ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError) ErrorName() string { ++ return "HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sHttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeaders.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = HttpDubboTranscoder_DubboMethodMapping_PassthroughSetting_PassthroughHeadersValidationError{} +diff --git a/contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.pb.go b/contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.pb.go +new file mode 100755 +index 00000000..671d875c +--- /dev/null ++++ b/contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.pb.go +@@ -0,0 +1,233 @@ ++// Code generated by protoc-gen-go. DO NOT EDIT. ++// versions: ++// protoc-gen-go v1.25.0 ++// protoc v3.18.0 ++// source: contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.proto ++ ++package envoy_extensions_filters_http_sentinel_v3 ++ ++import ( ++ _ "github.com/cncf/xds/go/udpa/annotations" ++ v3 "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/common/sentinel/v3" ++ v32 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" ++ v31 "github.com/envoyproxy/go-control-plane/envoy/type/v3" ++ _ "github.com/envoyproxy/protoc-gen-validate/validate" ++ proto "github.com/golang/protobuf/proto" ++ protoreflect "google.golang.org/protobuf/reflect/protoreflect" ++ protoimpl "google.golang.org/protobuf/runtime/protoimpl" ++ reflect "reflect" ++ sync "sync" ++) ++ ++const ( ++ // Verify that this generated code is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ++ // Verify that runtime/protoimpl is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ++) ++ ++// This is a compile-time assertion that a sufficiently up-to-date version ++// of the legacy proto package is being used. ++const _ = proto.ProtoPackageIsVersion4 ++ ++// [#protodoc-title: Sentinel] ++// [#comment:next free field: 2] ++type Sentinel struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ CommonConfig *v3.CommonConfig `protobuf:"bytes,1,opt,name=common_config,json=commonConfig,proto3" json:"common_config,omitempty"` ++ // The human readable prefix to use when emitting stats. ++ StatPrefix string `protobuf:"bytes,2,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` ++ // This field allows for a custom HTTP response status code to the downstream client when ++ // the request has been rate limited. ++ // Defaults to 429 (TooManyRequests). ++ // ++ // .. note:: ++ // If this is set to < 400, 429 will be used instead. ++ Status *v31.HttpStatus `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` ++ // Specifies a list of HTTP headers that should be added to each response for requests that ++ // have been rate limited. ++ ResponseHeadersToAdd []*v32.HeaderValueOption `protobuf:"bytes,4,rep,name=response_headers_to_add,json=responseHeadersToAdd,proto3" json:"response_headers_to_add,omitempty"` ++} ++ ++func (x *Sentinel) Reset() { ++ *x = Sentinel{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_msgTypes[0] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *Sentinel) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*Sentinel) ProtoMessage() {} ++ ++func (x *Sentinel) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_msgTypes[0] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use Sentinel.ProtoReflect.Descriptor instead. ++func (*Sentinel) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescGZIP(), []int{0} ++} ++ ++func (x *Sentinel) GetCommonConfig() *v3.CommonConfig { ++ if x != nil { ++ return x.CommonConfig ++ } ++ return nil ++} ++ ++func (x *Sentinel) GetStatPrefix() string { ++ if x != nil { ++ return x.StatPrefix ++ } ++ return "" ++} ++ ++func (x *Sentinel) GetStatus() *v31.HttpStatus { ++ if x != nil { ++ return x.Status ++ } ++ return nil ++} ++ ++func (x *Sentinel) GetResponseHeadersToAdd() []*v32.HeaderValueOption { ++ if x != nil { ++ return x.ResponseHeadersToAdd ++ } ++ return nil ++} ++ ++var File_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto protoreflect.FileDescriptor ++ ++var file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDesc = []byte{ ++ 0x0a, 0x40, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, ++ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x69, 0x6c, 0x74, 0x65, ++ 0x72, 0x73, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, ++ 0x2f, 0x76, 0x33, 0x2f, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x12, 0x29, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, ++ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, ++ 0x70, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x33, 0x1a, 0x40, 0x63, ++ 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x65, 0x78, 0x74, ++ 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2f, ++ 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2f, ++ 0x76, 0x33, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, ++ 0x1f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, ++ 0x72, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x1a, 0x1f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x76, 0x33, 0x2f, ++ 0x68, 0x74, 0x74, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x1a, 0x1d, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, ++ 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x1a, 0x21, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, ++ 0x6e, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, ++ 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb1, 0x02, 0x0a, ++ 0x08, 0x53, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x12, 0x5e, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, ++ 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, ++ 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x33, 0x2e, 0x43, ++ 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x0b, 0x73, 0x74, 0x61, ++ 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, ++ 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, ++ 0x66, 0x69, 0x78, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, ++ 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, ++ 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x68, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, ++ 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x64, ++ 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, ++ 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, ++ 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x10, 0x0a, 0x52, 0x14, 0x72, 0x65, 0x73, 0x70, ++ 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x41, 0x64, 0x64, ++ 0x42, 0x52, 0x0a, 0x37, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, ++ 0x79, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, ++ 0x6e, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, ++ 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x33, 0x42, 0x0d, 0x53, 0x65, 0x6e, ++ 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, ++ 0x06, 0x02, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++} ++ ++var ( ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescOnce sync.Once ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescData = file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDesc ++) ++ ++func file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescGZIP() []byte { ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescOnce.Do(func() { ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescData = protoimpl.X.CompressGZIP(file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescData) ++ }) ++ return file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDescData ++} ++ ++var file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_msgTypes = make([]protoimpl.MessageInfo, 1) ++var file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_goTypes = []interface{}{ ++ (*Sentinel)(nil), // 0: envoy.extensions.filters.http.sentinel.v3.Sentinel ++ (*v3.CommonConfig)(nil), // 1: envoy.extensions.filters.common.sentinel.v3.CommonConfig ++ (*v31.HttpStatus)(nil), // 2: envoy.type.v3.HttpStatus ++ (*v32.HeaderValueOption)(nil), // 3: envoy.config.core.v3.HeaderValueOption ++} ++var file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_depIdxs = []int32{ ++ 1, // 0: envoy.extensions.filters.http.sentinel.v3.Sentinel.common_config:type_name -> envoy.extensions.filters.common.sentinel.v3.CommonConfig ++ 2, // 1: envoy.extensions.filters.http.sentinel.v3.Sentinel.status:type_name -> envoy.type.v3.HttpStatus ++ 3, // 2: envoy.extensions.filters.http.sentinel.v3.Sentinel.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 3, // [3:3] is the sub-list for method output_type ++ 3, // [3:3] is the sub-list for method input_type ++ 3, // [3:3] is the sub-list for extension type_name ++ 3, // [3:3] is the sub-list for extension extendee ++ 0, // [0:3] is the sub-list for field type_name ++} ++ ++func init() { file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_init() } ++func file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_init() { ++ if File_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto != nil { ++ return ++ } ++ if !protoimpl.UnsafeEnabled { ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*Sentinel); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ } ++ type x struct{} ++ out := protoimpl.TypeBuilder{ ++ File: protoimpl.DescBuilder{ ++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), ++ RawDescriptor: file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDesc, ++ NumEnums: 0, ++ NumMessages: 1, ++ NumExtensions: 0, ++ NumServices: 0, ++ }, ++ GoTypes: file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_goTypes, ++ DependencyIndexes: file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_depIdxs, ++ MessageInfos: file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_msgTypes, ++ }.Build() ++ File_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto = out.File ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_rawDesc = nil ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_goTypes = nil ++ file_contrib_envoy_extensions_filters_http_sentinel_v3_sentinel_proto_depIdxs = nil ++} +diff --git a/contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.pb.validate.go b/contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.pb.validate.go +new file mode 100755 +index 00000000..085b3b6e +--- /dev/null ++++ b/contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.pb.validate.go +@@ -0,0 +1,147 @@ ++// Code generated by protoc-gen-validate. DO NOT EDIT. ++// source: contrib/envoy/extensions/filters/http/sentinel/v3/sentinel.proto ++ ++package envoy_extensions_filters_http_sentinel_v3 ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "net" ++ "net/mail" ++ "net/url" ++ "regexp" ++ "strings" ++ "time" ++ "unicode/utf8" ++ ++ "google.golang.org/protobuf/types/known/anypb" ++) ++ ++// ensure the imports are used ++var ( ++ _ = bytes.MinRead ++ _ = errors.New("") ++ _ = fmt.Print ++ _ = utf8.UTFMax ++ _ = (*regexp.Regexp)(nil) ++ _ = (*strings.Reader)(nil) ++ _ = net.IPv4len ++ _ = time.Duration(0) ++ _ = (*url.URL)(nil) ++ _ = (*mail.Address)(nil) ++ _ = anypb.Any{} ++) ++ ++// Validate checks the field values on Sentinel with the rules defined in the ++// proto definition for this message. If any rules are violated, an error is returned. ++func (m *Sentinel) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if v, ok := interface{}(m.GetCommonConfig()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return SentinelValidationError{ ++ field: "CommonConfig", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ if utf8.RuneCountInString(m.GetStatPrefix()) < 1 { ++ return SentinelValidationError{ ++ field: "StatPrefix", ++ reason: "value length must be at least 1 runes", ++ } ++ } ++ ++ if v, ok := interface{}(m.GetStatus()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return SentinelValidationError{ ++ field: "Status", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ if len(m.GetResponseHeadersToAdd()) > 10 { ++ return SentinelValidationError{ ++ field: "ResponseHeadersToAdd", ++ reason: "value must contain no more than 10 item(s)", ++ } ++ } ++ ++ for idx, item := range m.GetResponseHeadersToAdd() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return SentinelValidationError{ ++ field: fmt.Sprintf("ResponseHeadersToAdd[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ return nil ++} ++ ++// SentinelValidationError is the validation error returned by ++// Sentinel.Validate if the designated constraints aren't met. ++type SentinelValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e SentinelValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e SentinelValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e SentinelValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e SentinelValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e SentinelValidationError) ErrorName() string { return "SentinelValidationError" } ++ ++// Error satisfies the builtin error interface ++func (e SentinelValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sSentinel.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = SentinelValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = SentinelValidationError{} +diff --git a/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.pb.go b/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.pb.go +new file mode 100755 +index 00000000..51d662e8 +--- /dev/null ++++ b/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.pb.go +@@ -0,0 +1,156 @@ ++// Code generated by protoc-gen-go. DO NOT EDIT. ++// versions: ++// protoc-gen-go v1.25.0 ++// protoc v3.18.0 ++// source: contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.proto ++ ++package envoy_extensions_upstreams_http_dubbo_tcp_v3 ++ ++import ( ++ _ "github.com/cncf/xds/go/udpa/annotations" ++ proto "github.com/golang/protobuf/proto" ++ protoreflect "google.golang.org/protobuf/reflect/protoreflect" ++ protoimpl "google.golang.org/protobuf/runtime/protoimpl" ++ reflect "reflect" ++ sync "sync" ++) ++ ++const ( ++ // Verify that this generated code is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ++ // Verify that runtime/protoimpl is sufficiently up-to-date. ++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ++) ++ ++// This is a compile-time assertion that a sufficiently up-to-date version ++// of the legacy proto package is being used. ++const _ = proto.ProtoPackageIsVersion4 ++ ++// A connection pool which forwards downstream HTTP as TCP to upstream, ++// [#extension: envoy.upstreams.http.tcp] ++type DubboTcpConnectionPoolProto struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++} ++ ++func (x *DubboTcpConnectionPoolProto) Reset() { ++ *x = DubboTcpConnectionPoolProto{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_msgTypes[0] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *DubboTcpConnectionPoolProto) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*DubboTcpConnectionPoolProto) ProtoMessage() {} ++ ++func (x *DubboTcpConnectionPoolProto) ProtoReflect() protoreflect.Message { ++ mi := &file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_msgTypes[0] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use DubboTcpConnectionPoolProto.ProtoReflect.Descriptor instead. ++func (*DubboTcpConnectionPoolProto) Descriptor() ([]byte, []int) { ++ return file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescGZIP(), []int{0} ++} ++ ++var File_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto protoreflect.FileDescriptor ++ ++var file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDesc = []byte{ ++ 0x0a, 0x4e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, ++ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x75, 0x70, 0x73, 0x74, 0x72, ++ 0x65, 0x61, 0x6d, 0x73, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, ++ 0x74, 0x63, 0x70, 0x2f, 0x76, 0x33, 0x2f, 0x74, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, ++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x12, 0x2c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, ++ 0x6e, 0x73, 0x2e, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x2e, 0x68, 0x74, 0x74, ++ 0x70, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x63, 0x70, 0x2e, 0x76, 0x33, 0x1a, 0x1d, ++ 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, ++ 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1d, 0x0a, ++ 0x1b, 0x44, 0x75, 0x62, 0x62, 0x6f, 0x54, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, ++ 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x5e, 0x0a, 0x3a, ++ 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x75, ++ 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x64, 0x75, ++ 0x62, 0x62, 0x6f, 0x5f, 0x74, 0x63, 0x70, 0x2e, 0x76, 0x33, 0x42, 0x16, 0x54, 0x63, 0x70, 0x43, ++ 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x50, 0x72, 0x6f, ++ 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, ++} ++ ++var ( ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescOnce sync.Once ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescData = file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDesc ++) ++ ++func file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescGZIP() []byte { ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescOnce.Do(func() { ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescData = protoimpl.X.CompressGZIP(file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescData) ++ }) ++ return file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDescData ++} ++ ++var file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_msgTypes = make([]protoimpl.MessageInfo, 1) ++var file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_goTypes = []interface{}{ ++ (*DubboTcpConnectionPoolProto)(nil), // 0: envoy.extensions.upstreams.http.dubbo_tcp.v3.DubboTcpConnectionPoolProto ++} ++var file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_depIdxs = []int32{ ++ 0, // [0:0] is the sub-list for method output_type ++ 0, // [0:0] is the sub-list for method input_type ++ 0, // [0:0] is the sub-list for extension type_name ++ 0, // [0:0] is the sub-list for extension extendee ++ 0, // [0:0] is the sub-list for field type_name ++} ++ ++func init() { ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_init() ++} ++func file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_init() { ++ if File_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto != nil { ++ return ++ } ++ if !protoimpl.UnsafeEnabled { ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*DubboTcpConnectionPoolProto); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ } ++ type x struct{} ++ out := protoimpl.TypeBuilder{ ++ File: protoimpl.DescBuilder{ ++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), ++ RawDescriptor: file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDesc, ++ NumEnums: 0, ++ NumMessages: 1, ++ NumExtensions: 0, ++ NumServices: 0, ++ }, ++ GoTypes: file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_goTypes, ++ DependencyIndexes: file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_depIdxs, ++ MessageInfos: file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_msgTypes, ++ }.Build() ++ File_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto = out.File ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_rawDesc = nil ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_goTypes = nil ++ file_contrib_envoy_extensions_upstreams_http_dubbo_tcp_v3_tcp_connection_pool_proto_depIdxs = nil ++} +diff --git a/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.pb.validate.go b/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.pb.validate.go +new file mode 100755 +index 00000000..9c7d25a8 +--- /dev/null ++++ b/contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.pb.validate.go +@@ -0,0 +1,102 @@ ++// Code generated by protoc-gen-validate. DO NOT EDIT. ++// source: contrib/envoy/extensions/upstreams/http/dubbo_tcp/v3/tcp_connection_pool.proto ++ ++package envoy_extensions_upstreams_http_dubbo_tcp_v3 ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "net" ++ "net/mail" ++ "net/url" ++ "regexp" ++ "strings" ++ "time" ++ "unicode/utf8" ++ ++ "google.golang.org/protobuf/types/known/anypb" ++) ++ ++// ensure the imports are used ++var ( ++ _ = bytes.MinRead ++ _ = errors.New("") ++ _ = fmt.Print ++ _ = utf8.UTFMax ++ _ = (*regexp.Regexp)(nil) ++ _ = (*strings.Reader)(nil) ++ _ = net.IPv4len ++ _ = time.Duration(0) ++ _ = (*url.URL)(nil) ++ _ = (*mail.Address)(nil) ++ _ = anypb.Any{} ++) ++ ++// Validate checks the field values on DubboTcpConnectionPoolProto with the ++// rules defined in the proto definition for this message. If any rules are ++// violated, an error is returned. ++func (m *DubboTcpConnectionPoolProto) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ return nil ++} ++ ++// DubboTcpConnectionPoolProtoValidationError is the validation error returned ++// by DubboTcpConnectionPoolProto.Validate if the designated constraints ++// aren't met. ++type DubboTcpConnectionPoolProtoValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e DubboTcpConnectionPoolProtoValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e DubboTcpConnectionPoolProtoValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e DubboTcpConnectionPoolProtoValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e DubboTcpConnectionPoolProtoValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e DubboTcpConnectionPoolProtoValidationError) ErrorName() string { ++ return "DubboTcpConnectionPoolProtoValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e DubboTcpConnectionPoolProtoValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sDubboTcpConnectionPoolProto.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = DubboTcpConnectionPoolProtoValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = DubboTcpConnectionPoolProtoValidationError{} +diff --git a/envoy/COMMIT b/envoy/COMMIT +index 7bc56cf9..5403e890 100644 +--- a/envoy/COMMIT ++++ b/envoy/COMMIT +@@ -1 +1 @@ +-54b686bb5f16cae0d506293fbefb82ab5588c3d3 +\ No newline at end of file ++a16444a83b5157a518249541e162a68376812902 +\ No newline at end of file +diff --git a/envoy/config/cluster/v3/cluster.pb.go b/envoy/config/cluster/v3/cluster.pb.go +index cc2bff06..2251cdd8 100755 +--- a/envoy/config/cluster/v3/cluster.pb.go ++++ b/envoy/config/cluster/v3/cluster.pb.go +@@ -1988,12 +1988,16 @@ type Cluster_SlowStartConfig struct { + // By tuning the parameter, is possible to achieve polynomial or exponential shape of ramp-up curve. + // + // During slow start window, effective weight of an endpoint would be scaled with time factor and aggression: +- // `new_weight = weight * time_factor ^ (1 / aggression)`, ++ // `new_weight = weight * max(min_weight_percent, time_factor ^ (1 / aggression))`, + // where `time_factor=(time_since_start_seconds / slow_start_time_seconds)`. + // + // As time progresses, more and more traffic would be sent to endpoint, which is in slow start window. + // Once host exits slow start, time_factor and aggression no longer affect its weight. + Aggression *v32.RuntimeDouble `protobuf:"bytes,2,opt,name=aggression,proto3" json:"aggression,omitempty"` ++ // Configures the minimum percentage of origin weight that avoids too small new weight, ++ // which may cause endpoints in slow start mode receive no traffic in slow start window. ++ // If not specified, the default is 10%. ++ MinWeightPercent *v33.Percent `protobuf:"bytes,3,opt,name=min_weight_percent,json=minWeightPercent,proto3" json:"min_weight_percent,omitempty"` + } + + func (x *Cluster_SlowStartConfig) Reset() { +@@ -2042,6 +2046,13 @@ func (x *Cluster_SlowStartConfig) GetAggression() *v32.RuntimeDouble { + return nil + } + ++func (x *Cluster_SlowStartConfig) GetMinWeightPercent() *v33.Percent { ++ if x != nil { ++ return x.MinWeightPercent ++ } ++ return nil ++} ++ + // Specific configuration for the RoundRobin load balancing policy. + type Cluster_RoundRobinLbConfig struct { + state protoimpl.MessageState +@@ -3086,7 +3097,7 @@ var file_envoy_config_cluster_v3_cluster_proto_rawDesc = []byte{ + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x64, 0x73, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, +- 0xac, 0x4e, 0x0a, 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x6f, 0x0a, 0x18, 0x74, ++ 0xf2, 0x4e, 0x0a, 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x6f, 0x0a, 0x18, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x2b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, + 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, +@@ -3478,7 +3489,7 @@ var file_envoy_config_cluster_v3_cluster_proto_rawDesc = []byte{ + 0x45, 0x54, 0x10, 0x02, 0x3a, 0x2a, 0x9a, 0xc5, 0x88, 0x1e, 0x25, 0x0a, 0x23, 0x65, 0x6e, 0x76, + 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x2e, 0x4c, 0x62, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x1a, 0x9d, 0x01, 0x0a, 0x0f, 0x53, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, ++ 0x1a, 0xe3, 0x01, 0x0a, 0x0f, 0x53, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x45, 0x0a, 0x11, 0x73, 0x6c, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, +@@ -3488,283 +3499,287 @@ var file_envoy_config_cluster_v3_cluster_proto_rawDesc = []byte{ + 0x23, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x6f, + 0x75, 0x62, 0x6c, 0x65, 0x52, 0x0a, 0x61, 0x67, 0x67, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, +- 0x1a, 0x72, 0x0a, 0x12, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x4c, 0x62, +- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x11, 0x73, 0x6c, 0x6f, 0x77, 0x5f, 0x73, +- 0x74, 0x61, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, +- 0x74, 0x65, 0x72, 0x2e, 0x53, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x52, 0x0f, 0x73, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xc5, 0x02, 0x0a, 0x14, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, +- 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x48, 0x0a, +- 0x0c, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, +- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, +- 0x65, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x28, 0x02, 0x52, 0x0b, 0x63, 0x68, 0x6f, 0x69, +- 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x13, 0x61, 0x63, 0x74, 0x69, 0x76, +- 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x18, 0x02, +- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x75, 0x6e, 0x74, +- 0x69, 0x6d, 0x65, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x61, 0x63, 0x74, 0x69, 0x76, +- 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x69, 0x61, 0x73, 0x12, 0x5c, 0x0a, 0x11, ++ 0x12, 0x44, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x70, ++ 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x65, 0x72, ++ 0x63, 0x65, 0x6e, 0x74, 0x52, 0x10, 0x6d, 0x69, 0x6e, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x50, ++ 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x1a, 0x72, 0x0a, 0x12, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, ++ 0x6f, 0x62, 0x69, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x11, + 0x73, 0x6c, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x6c, 0x6f, 0x77, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x73, 0x6c, 0x6f, 0x77, 0x53, +- 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x30, 0x9a, 0xc5, 0x88, 0x1e, +- 0x2b, 0x0a, 0x29, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, +- 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, +- 0x75, 0x65, 0x73, 0x74, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x91, 0x03, 0x0a, +- 0x10, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x12, 0x54, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, +- 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, ++ 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xc5, 0x02, 0x0a, 0x14, 0x4c, ++ 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x62, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x12, 0x48, 0x0a, 0x0c, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, ++ 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, ++ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, ++ 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x28, 0x02, ++ 0x52, 0x0b, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x53, 0x0a, ++ 0x13, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, ++ 0x62, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, ++ 0x33, 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x52, ++ 0x11, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x69, ++ 0x61, 0x73, 0x12, 0x5c, 0x0a, 0x11, 0x73, 0x6c, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, ++ 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, ++ 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, ++ 0x53, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, ++ 0x0f, 0x73, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x3a, 0x30, 0x9a, 0xc5, 0x88, 0x1e, 0x2b, 0x0a, 0x29, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, ++ 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x65, ++ 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x1a, 0x91, 0x03, 0x0a, 0x10, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x4c, ++ 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x54, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, ++ 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, ++ 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x32, 0x05, 0x18, 0x80, 0x80, 0x80, 0x04, 0x52, 0x0f, 0x6d, 0x69, ++ 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x6d, 0x0a, ++ 0x0d, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, ++ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, ++ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x4c, ++ 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x46, 0x75, 0x6e, 0x63, ++ 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0c, ++ 0x68, 0x61, 0x73, 0x68, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x54, 0x0a, 0x11, ++ 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, ++ 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, ++ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x32, 0x05, 0x18, 0x80, 0x80, 0x80, ++ 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, ++ 0x7a, 0x65, 0x22, 0x2e, 0x0a, 0x0c, 0x48, 0x61, 0x73, 0x68, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, ++ 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x58, 0x58, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, ++ 0x11, 0x0a, 0x0d, 0x4d, 0x55, 0x52, 0x4d, 0x55, 0x52, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x32, ++ 0x10, 0x01, 0x3a, 0x2c, 0x9a, 0xc5, 0x88, 0x1e, 0x27, 0x0a, 0x25, 0x65, 0x6e, 0x76, 0x6f, 0x79, ++ 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, ++ 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x1a, 0x59, 0x0a, 0x0e, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, ++ 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x47, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, ++ 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, + 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x32, +- 0x05, 0x18, 0x80, 0x80, 0x80, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, +- 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x6d, 0x0a, 0x0d, 0x68, 0x61, 0x73, 0x68, 0x5f, +- 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, +- 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, +- 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, +- 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, +- 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x68, 0x61, 0x73, 0x68, 0x46, 0x75, +- 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x54, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, +- 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, +- 0x0a, 0xfa, 0x42, 0x07, 0x32, 0x05, 0x18, 0x80, 0x80, 0x80, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x78, +- 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x2e, 0x0a, 0x0c, +- 0x48, 0x61, 0x73, 0x68, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, +- 0x58, 0x58, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x55, 0x52, +- 0x4d, 0x55, 0x52, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x32, 0x10, 0x01, 0x3a, 0x2c, 0x9a, 0xc5, +- 0x88, 0x1e, 0x27, 0x0a, 0x25, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, +- 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, +- 0x73, 0x68, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, +- 0x1a, 0x59, 0x0a, 0x0e, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x12, 0x47, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, +- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, +- 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x32, 0x05, 0x18, 0xcb, 0x96, 0xb1, 0x02, +- 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x6e, 0x0a, 0x13, 0x4f, +- 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x73, 0x74, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x68, +- 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x73, 0x65, +- 0x48, 0x74, 0x74, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3a, 0x2f, 0x9a, 0xc5, 0x88, 0x1e, +- 0x2a, 0x0a, 0x28, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, +- 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, +- 0x44, 0x73, 0x74, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xfc, 0x0a, 0x0a, 0x0e, +- 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, +- 0x0a, 0x17, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x5f, +- 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, +- 0x16, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, +- 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x15, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, +- 0x50, 0x61, 0x6e, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x74, +- 0x0a, 0x14, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x61, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x6c, 0x62, 0x5f, +- 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x65, ++ 0x05, 0x18, 0xcb, 0x96, 0xb1, 0x02, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x69, 0x7a, ++ 0x65, 0x1a, 0x6e, 0x0a, 0x13, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x73, 0x74, ++ 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x5f, ++ 0x68, 0x74, 0x74, 0x70, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, ++ 0x08, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x48, 0x74, 0x74, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, ++ 0x3a, 0x2f, 0x9a, 0xc5, 0x88, 0x1e, 0x2a, 0x0a, 0x28, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, ++ 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x72, ++ 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x73, 0x74, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x1a, 0xfc, 0x0a, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x17, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x5f, ++ 0x70, 0x61, 0x6e, 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, ++ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, ++ 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x15, 0x68, ++ 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, ++ 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x74, 0x0a, 0x14, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x61, 0x77, 0x61, ++ 0x72, 0x65, 0x5f, 0x6c, 0x62, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, ++ 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x5a, 0x6f, 0x6e, 0x65, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x62, 0x43, ++ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x11, 0x7a, 0x6f, 0x6e, 0x65, 0x41, 0x77, 0x61, ++ 0x72, 0x65, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x89, 0x01, 0x0a, 0x1b, 0x6c, ++ 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, ++ 0x5f, 0x6c, 0x62, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x48, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, ++ 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, ++ 0x65, 0x64, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x18, 0x6c, 0x6f, ++ 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4c, 0x62, ++ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x13, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, ++ 0x5f, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x04, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, ++ 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, ++ 0x77, 0x12, 0x43, 0x0a, 0x1f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, ++ 0x68, 0x6f, 0x73, 0x74, 0x73, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x5f, 0x66, 0x69, 0x72, 0x73, ++ 0x74, 0x5f, 0x68, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x69, 0x67, 0x6e, 0x6f, ++ 0x72, 0x65, 0x4e, 0x65, 0x77, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x46, ++ 0x69, 0x72, 0x73, 0x74, 0x48, 0x63, 0x12, 0x4d, 0x0a, 0x24, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, ++ 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x6f, 0x6e, 0x5f, 0x68, ++ 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x06, ++ 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, ++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x43, ++ 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x1c, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, ++ 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x62, 0x5f, ++ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x65, + 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, +- 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x5a, 0x6f, +- 0x6e, 0x65, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, +- 0x00, 0x52, 0x11, 0x7a, 0x6f, 0x6e, 0x65, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x62, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x12, 0x89, 0x01, 0x0a, 0x1b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, +- 0x79, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x62, 0x5f, 0x63, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x65, 0x6e, 0x76, +- 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, +- 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, +- 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, +- 0x6c, 0x69, 0x74, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4c, 0x62, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x18, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, +- 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x12, 0x49, 0x0a, 0x13, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x72, 0x67, 0x65, +- 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, +- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, +- 0x4d, 0x65, 0x72, 0x67, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x43, 0x0a, 0x1f, 0x69, +- 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x5f, +- 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x68, 0x63, 0x18, 0x05, +- 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4e, 0x65, 0x77, 0x48, +- 0x6f, 0x73, 0x74, 0x73, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x46, 0x69, 0x72, 0x73, 0x74, 0x48, 0x63, +- 0x12, 0x4d, 0x0a, 0x24, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, +- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x6f, 0x6e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, +- 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, +- 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, +- 0x4f, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, +- 0x8a, 0x01, 0x0a, 0x1c, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, +- 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x62, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, +- 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, +- 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, +- 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x52, 0x19, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, +- 0x68, 0x69, 0x6e, 0x67, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x8d, 0x02, 0x0a, +- 0x11, 0x5a, 0x6f, 0x6e, 0x65, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x12, 0x3f, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, +- 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x65, 0x72, 0x63, +- 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, +- 0x6c, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x10, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, +- 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, +- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x6d, 0x69, 0x6e, +- 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x66, +- 0x61, 0x69, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, +- 0x61, 0x6e, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x66, 0x61, 0x69, 0x6c, +- 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x4f, 0x6e, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x3a, 0x3c, +- 0x9a, 0xc5, 0x88, 0x1e, 0x37, 0x0a, 0x35, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, ++ 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, ++ 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x4c, ++ 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x19, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, ++ 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x1a, 0x8d, 0x02, 0x0a, 0x11, 0x5a, 0x6f, 0x6e, 0x65, 0x41, 0x77, 0x61, 0x72, 0x65, ++ 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3f, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x74, ++ 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, ++ 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, ++ 0x33, 0x2e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, ++ 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x10, 0x6d, 0x69, 0x6e, ++ 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, ++ 0x65, 0x52, 0x0e, 0x6d, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x69, 0x7a, ++ 0x65, 0x12, 0x31, 0x0a, 0x15, 0x66, 0x61, 0x69, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, ++ 0x63, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, ++ 0x52, 0x12, 0x66, 0x61, 0x69, 0x6c, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x4f, 0x6e, 0x50, ++ 0x61, 0x6e, 0x69, 0x63, 0x3a, 0x3c, 0x9a, 0xc5, 0x88, 0x1e, 0x37, 0x0a, 0x35, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, ++ 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x2e, 0x5a, 0x6f, 0x6e, 0x65, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x1a, 0x5f, 0x0a, 0x18, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x57, 0x65, ++ 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x43, ++ 0x9a, 0xc5, 0x88, 0x1e, 0x3e, 0x0a, 0x3c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, +- 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x5a, 0x6f, 0x6e, 0x65, 0x41, +- 0x77, 0x61, 0x72, 0x65, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x5f, 0x0a, 0x18, +- 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, +- 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x43, 0x9a, 0xc5, 0x88, 0x1e, 0x3e, 0x0a, +- 0x3c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, +- 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x57, 0x65, 0x69, +- 0x67, 0x68, 0x74, 0x65, 0x64, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xf1, 0x01, +- 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, +- 0x69, 0x6e, 0x67, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x18, 0x75, +- 0x73, 0x65, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, +- 0x68, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x75, +- 0x73, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x48, 0x61, 0x73, +- 0x68, 0x69, 0x6e, 0x67, 0x12, 0x55, 0x0a, 0x13, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x62, 0x61, 0x6c, +- 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, +- 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x28, 0x64, 0x52, 0x11, 0x68, 0x61, 0x73, 0x68, 0x42, 0x61, +- 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x3a, 0x44, 0x9a, 0xc5, 0x88, +- 0x1e, 0x3f, 0x0a, 0x3d, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, +- 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, +- 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, ++ 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, ++ 0x69, 0x74, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4c, 0x62, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x1a, 0xf1, 0x01, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x3a, 0x2a, 0x9a, 0xc5, 0x88, 0x1e, 0x25, 0x0a, 0x23, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x67, 0x12, 0x37, 0x0a, 0x18, 0x75, 0x73, 0x65, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, ++ 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, ++ 0x01, 0x28, 0x08, 0x52, 0x15, 0x75, 0x73, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, ++ 0x46, 0x6f, 0x72, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x55, 0x0a, 0x13, 0x68, 0x61, ++ 0x73, 0x68, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, ++ 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, ++ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x28, 0x64, 0x52, 0x11, ++ 0x68, 0x61, 0x73, 0x68, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x46, 0x61, 0x63, 0x74, 0x6f, ++ 0x72, 0x3a, 0x44, 0x9a, 0xc5, 0x88, 0x1e, 0x3f, 0x0a, 0x3d, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, +- 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x1b, 0x0a, +- 0x19, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0xd2, 0x01, 0x0a, 0x0b, 0x52, +- 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x61, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x62, 0x61, +- 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0e, 0xfa, 0x42, +- 0x0b, 0xaa, 0x01, 0x08, 0x08, 0x01, 0x2a, 0x04, 0x10, 0xc0, 0x84, 0x3d, 0x52, 0x0c, 0x62, 0x61, +- 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x4a, 0x0a, 0x0c, 0x6d, 0x61, +- 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, +- 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, +- 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0c, 0xfa, 0x42, 0x09, +- 0xaa, 0x01, 0x06, 0x2a, 0x04, 0x10, 0xc0, 0x84, 0x3d, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x49, 0x6e, +- 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x3a, 0x27, 0x9a, 0xc5, 0x88, 0x1e, 0x22, 0x0a, 0x20, 0x65, +- 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, +- 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x61, 0x74, 0x65, 0x1a, +- 0x83, 0x02, 0x0a, 0x10, 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6f, +- 0x6c, 0x69, 0x63, 0x79, 0x12, 0x78, 0x0a, 0x1d, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x73, 0x74, +- 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, +- 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, +- 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x6f, +- 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x17, 0xfa, 0x42, 0x14, 0x12, 0x12, +- 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0xf0, 0x3f, 0x52, 0x1a, 0x70, 0x65, 0x72, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, +- 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x75, +- 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x65, +- 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x02, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, +- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, +- 0x65, 0x42, 0x17, 0xfa, 0x42, 0x14, 0x12, 0x12, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, +- 0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x52, 0x19, 0x70, 0x72, 0x65, 0x64, +- 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, +- 0x52, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0x66, 0x0a, 0x22, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, +- 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4f, +- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, +- 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, +- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, +- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, +- 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x57, 0x0a, +- 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, +- 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x54, +- 0x52, 0x49, 0x43, 0x54, 0x5f, 0x44, 0x4e, 0x53, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x4f, +- 0x47, 0x49, 0x43, 0x41, 0x4c, 0x5f, 0x44, 0x4e, 0x53, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x45, +- 0x44, 0x53, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c, +- 0x5f, 0x44, 0x53, 0x54, 0x10, 0x04, 0x22, 0xa4, 0x01, 0x0a, 0x08, 0x4c, 0x62, 0x50, 0x6f, 0x6c, +- 0x69, 0x63, 0x79, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, +- 0x49, 0x4e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x4c, 0x45, 0x41, 0x53, 0x54, 0x5f, 0x52, 0x45, +- 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x49, 0x4e, 0x47, 0x5f, +- 0x48, 0x41, 0x53, 0x48, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x41, 0x4e, 0x44, 0x4f, 0x4d, +- 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x47, 0x4c, 0x45, 0x56, 0x10, 0x05, 0x12, 0x14, +- 0x0a, 0x10, 0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, +- 0x45, 0x44, 0x10, 0x06, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, +- 0x41, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x43, 0x4f, +- 0x4e, 0x46, 0x49, 0x47, 0x10, 0x07, 0x22, 0x04, 0x08, 0x04, 0x10, 0x04, 0x2a, 0x0f, 0x4f, 0x52, +- 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x44, 0x53, 0x54, 0x5f, 0x4c, 0x42, 0x22, 0x47, 0x0a, +- 0x0f, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, +- 0x12, 0x08, 0x0a, 0x04, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x56, 0x34, +- 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x56, 0x36, 0x5f, 0x4f, 0x4e, +- 0x4c, 0x59, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x56, 0x34, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x45, +- 0x52, 0x52, 0x45, 0x44, 0x10, 0x03, 0x22, 0x54, 0x0a, 0x18, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, +- 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, +- 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, +- 0x55, 0x52, 0x45, 0x44, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x00, 0x12, +- 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x53, 0x54, 0x52, 0x45, 0x41, +- 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x01, 0x3a, 0x1b, 0x9a, 0xc5, +- 0x88, 0x1e, 0x16, 0x0a, 0x14, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, +- 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x42, 0x18, 0x0a, 0x16, 0x63, 0x6c, 0x75, +- 0x73, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x74, +- 0x79, 0x70, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x6c, 0x62, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x4a, 0x04, 0x08, 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x07, +- 0x10, 0x08, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, 0x08, 0x23, 0x10, 0x24, 0x52, 0x05, +- 0x68, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x0b, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, +- 0x78, 0x74, 0x52, 0x1a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, +- 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xda, +- 0x02, 0x0a, 0x13, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, +- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4f, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, +- 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, +- 0x76, 0x33, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, +- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, +- 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0xc8, 0x01, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, +- 0x63, 0x79, 0x12, 0x60, 0x0a, 0x16, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, +- 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, +- 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, +- 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, +- 0x74, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x2e, 0x9a, 0xc5, 0x88, 0x1e, 0x29, 0x0a, 0x27, 0x65, 0x6e, 0x76, +- 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, +- 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, +- 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, +- 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x04, +- 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x0c, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x3a, 0x27, 0x9a, 0xc5, 0x88, 0x1e, 0x22, 0x0a, 0x20, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, +- 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x82, 0x01, 0x0a, 0x12, +- 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x69, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, +- 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x65, 0x6e, 0x76, +- 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, +- 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x26, 0x9a, 0xc5, 0x88, 0x1e, 0x21, 0x0a, +- 0x1f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, +- 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x69, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x22, 0x93, 0x01, 0x0a, 0x19, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, +- 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x47, +- 0x0a, 0x0d, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, +- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x63, 0x70, +- 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x52, 0x0c, 0x74, 0x63, 0x70, 0x4b, 0x65, +- 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x3a, 0x2d, 0x9a, 0xc5, 0x88, 0x1e, 0x28, 0x0a, 0x26, +- 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x73, +- 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, +- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x72, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x43, +- 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x74, +- 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, +- 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x75, 0x64, +- 0x67, 0x65, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, +- 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x18, 0x02, +- 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, +- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x42, 0x3f, 0x0a, 0x25, 0x69, 0x6f, +- 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, +- 0x2e, 0x76, 0x33, 0x42, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, +- 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, +- 0x74, 0x6f, 0x33, ++ 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, ++ 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x4c, ++ 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x2a, 0x9a, 0xc5, 0x88, 0x1e, 0x25, 0x0a, 0x23, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, ++ 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x62, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x42, 0x1b, 0x0a, 0x19, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, ++ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, ++ 0x1a, 0xd2, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x61, 0x74, 0x65, ++ 0x12, 0x4e, 0x0a, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, ++ 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, ++ 0x6f, 0x6e, 0x42, 0x0e, 0xfa, 0x42, 0x0b, 0xaa, 0x01, 0x08, 0x08, 0x01, 0x2a, 0x04, 0x10, 0xc0, ++ 0x84, 0x3d, 0x52, 0x0c, 0x62, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, ++ 0x12, 0x4a, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, ++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, ++ 0x6e, 0x42, 0x0c, 0xfa, 0x42, 0x09, 0xaa, 0x01, 0x06, 0x2a, 0x04, 0x10, 0xc0, 0x84, 0x3d, 0x52, ++ 0x0b, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x3a, 0x27, 0x9a, 0xc5, ++ 0x88, 0x1e, 0x22, 0x0a, 0x20, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, ++ 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, ++ 0x68, 0x52, 0x61, 0x74, 0x65, 0x1a, 0x83, 0x02, 0x0a, 0x10, 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, ++ 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x78, 0x0a, 0x1d, 0x70, 0x65, ++ 0x72, 0x5f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x65, 0x63, 0x6f, ++ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, ++ 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x62, 0x75, 0x66, 0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, ++ 0x17, 0xfa, 0x42, 0x14, 0x12, 0x12, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x29, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x52, 0x1a, 0x70, 0x65, 0x72, 0x55, 0x70, 0x73, ++ 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, ++ 0x61, 0x74, 0x69, 0x6f, 0x12, 0x75, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, ++ 0x76, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x61, ++ 0x74, 0x69, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, ++ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x6f, 0x75, 0x62, ++ 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x17, 0xfa, 0x42, 0x14, 0x12, 0x12, 0x19, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, ++ 0x52, 0x19, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x50, 0x72, 0x65, 0x63, ++ 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0x66, 0x0a, 0x22, 0x54, ++ 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, ++ 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, ++ 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, ++ 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, ++ 0x02, 0x38, 0x01, 0x22, 0x57, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, ++ 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x00, ++ 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x5f, 0x44, 0x4e, 0x53, 0x10, 0x01, ++ 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x4f, 0x47, 0x49, 0x43, 0x41, 0x4c, 0x5f, 0x44, 0x4e, 0x53, 0x10, ++ 0x02, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x44, 0x53, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x52, ++ 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x44, 0x53, 0x54, 0x10, 0x04, 0x22, 0xa4, 0x01, 0x0a, ++ 0x08, 0x4c, 0x62, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x4f, 0x55, ++ 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x4c, 0x45, ++ 0x41, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0d, 0x0a, ++ 0x09, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, ++ 0x52, 0x41, 0x4e, 0x44, 0x4f, 0x4d, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x47, 0x4c, ++ 0x45, 0x56, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x5f, ++ 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x44, 0x10, 0x06, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x4f, ++ 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x4f, 0x4c, ++ 0x49, 0x43, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x07, 0x22, 0x04, 0x08, 0x04, ++ 0x10, 0x04, 0x2a, 0x0f, 0x4f, 0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x44, 0x53, 0x54, ++ 0x5f, 0x4c, 0x42, 0x22, 0x47, 0x0a, 0x0f, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, ++ 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x00, ++ 0x12, 0x0b, 0x0a, 0x07, 0x56, 0x34, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01, 0x12, 0x0b, 0x0a, ++ 0x07, 0x56, 0x36, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x56, 0x34, ++ 0x5f, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x52, 0x45, 0x44, 0x10, 0x03, 0x22, 0x54, 0x0a, 0x18, ++ 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x53, ++ 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, 0x5f, ++ 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x45, 0x44, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, ++ 0x43, 0x4f, 0x4c, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, 0x5f, 0x44, 0x4f, 0x57, ++ 0x4e, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, ++ 0x10, 0x01, 0x3a, 0x1b, 0x9a, 0xc5, 0x88, 0x1e, 0x16, 0x0a, 0x14, 0x65, 0x6e, 0x76, 0x6f, 0x79, ++ 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x42, ++ 0x18, 0x0a, 0x16, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, ++ 0x76, 0x65, 0x72, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x6c, 0x62, 0x5f, ++ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x04, 0x08, 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x0f, ++ 0x10, 0x10, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, ++ 0x08, 0x23, 0x10, 0x24, 0x52, 0x05, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x0b, 0x74, 0x6c, 0x73, ++ 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x1a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, ++ 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x6f, 0x70, 0x74, ++ 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xda, 0x02, 0x0a, 0x13, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, ++ 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4f, 0x0a, 0x08, ++ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6c, ++ 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, ++ 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, ++ 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0xc8, 0x01, ++ 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x60, 0x0a, 0x16, 0x74, 0x79, 0x70, 0x65, ++ 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, ++ 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, ++ 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x74, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, ++ 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x2e, 0x9a, 0xc5, 0x88, 0x1e, ++ 0x29, 0x0a, 0x27, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, ++ 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, ++ 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, ++ 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x06, 0x63, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x0c, 0x74, 0x79, 0x70, 0x65, ++ 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x27, 0x9a, 0xc5, 0x88, 0x1e, 0x22, 0x0a, ++ 0x20, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x6f, ++ 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, ++ 0x79, 0x22, 0x82, 0x01, 0x0a, 0x12, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x69, ++ 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, ++ 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x1d, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, ++ 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x26, ++ 0x9a, 0xc5, 0x88, 0x1e, 0x21, 0x0a, 0x1f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, ++ 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x69, 0x6e, 0x64, ++ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x93, 0x01, 0x0a, 0x19, 0x55, 0x70, 0x73, 0x74, 0x72, ++ 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, ++ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, ++ 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, ++ 0x76, 0x33, 0x2e, 0x54, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x52, ++ 0x0c, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x3a, 0x2d, 0x9a, ++ 0xc5, 0x88, 0x1e, 0x28, 0x0a, 0x26, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, ++ 0x76, 0x32, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, ++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x72, 0x0a, 0x11, ++ 0x54, 0x72, 0x61, 0x63, 0x6b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, ++ 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x62, 0x75, 0x64, ++ 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, ++ 0x6f, 0x75, 0x74, 0x42, 0x75, 0x64, 0x67, 0x65, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, ++ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x73, ++ 0x69, 0x7a, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x72, 0x65, 0x71, 0x75, ++ 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, ++ 0x42, 0x3f, 0x0a, 0x25, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, ++ 0x79, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, ++ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x42, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, ++ 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, 0x10, ++ 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +@@ -3838,8 +3853,8 @@ var file_envoy_config_cluster_v3_cluster_proto_goTypes = []interface{}{ + (*_struct.Struct)(nil), // 53: google.protobuf.Struct + (*any.Any)(nil), // 54: google.protobuf.Any + (*v32.RuntimeDouble)(nil), // 55: envoy.config.core.v3.RuntimeDouble +- (*wrappers.UInt64Value)(nil), // 56: google.protobuf.UInt64Value +- (*v33.Percent)(nil), // 57: envoy.type.v3.Percent ++ (*v33.Percent)(nil), // 56: envoy.type.v3.Percent ++ (*wrappers.UInt64Value)(nil), // 57: google.protobuf.UInt64Value + (*wrappers.DoubleValue)(nil), // 58: google.protobuf.DoubleValue + } + var file_envoy_config_cluster_v3_cluster_proto_depIdxs = []int32{ +@@ -3899,34 +3914,35 @@ var file_envoy_config_cluster_v3_cluster_proto_depIdxs = []int32{ + 27, // 53: envoy.config.cluster.v3.Cluster.LbSubsetConfig.subset_selectors:type_name -> envoy.config.cluster.v3.Cluster.LbSubsetConfig.LbSubsetSelector + 33, // 54: envoy.config.cluster.v3.Cluster.SlowStartConfig.slow_start_window:type_name -> google.protobuf.Duration + 55, // 55: envoy.config.cluster.v3.Cluster.SlowStartConfig.aggression:type_name -> envoy.config.core.v3.RuntimeDouble +- 17, // 56: envoy.config.cluster.v3.Cluster.RoundRobinLbConfig.slow_start_config:type_name -> envoy.config.cluster.v3.Cluster.SlowStartConfig +- 34, // 57: envoy.config.cluster.v3.Cluster.LeastRequestLbConfig.choice_count:type_name -> google.protobuf.UInt32Value +- 55, // 58: envoy.config.cluster.v3.Cluster.LeastRequestLbConfig.active_request_bias:type_name -> envoy.config.core.v3.RuntimeDouble +- 17, // 59: envoy.config.cluster.v3.Cluster.LeastRequestLbConfig.slow_start_config:type_name -> envoy.config.cluster.v3.Cluster.SlowStartConfig +- 56, // 60: envoy.config.cluster.v3.Cluster.RingHashLbConfig.minimum_ring_size:type_name -> google.protobuf.UInt64Value +- 6, // 61: envoy.config.cluster.v3.Cluster.RingHashLbConfig.hash_function:type_name -> envoy.config.cluster.v3.Cluster.RingHashLbConfig.HashFunction +- 56, // 62: envoy.config.cluster.v3.Cluster.RingHashLbConfig.maximum_ring_size:type_name -> google.protobuf.UInt64Value +- 56, // 63: envoy.config.cluster.v3.Cluster.MaglevLbConfig.table_size:type_name -> google.protobuf.UInt64Value +- 57, // 64: envoy.config.cluster.v3.Cluster.CommonLbConfig.healthy_panic_threshold:type_name -> envoy.type.v3.Percent +- 28, // 65: envoy.config.cluster.v3.Cluster.CommonLbConfig.zone_aware_lb_config:type_name -> envoy.config.cluster.v3.Cluster.CommonLbConfig.ZoneAwareLbConfig +- 29, // 66: envoy.config.cluster.v3.Cluster.CommonLbConfig.locality_weighted_lb_config:type_name -> envoy.config.cluster.v3.Cluster.CommonLbConfig.LocalityWeightedLbConfig +- 33, // 67: envoy.config.cluster.v3.Cluster.CommonLbConfig.update_merge_window:type_name -> google.protobuf.Duration +- 30, // 68: envoy.config.cluster.v3.Cluster.CommonLbConfig.consistent_hashing_lb_config:type_name -> envoy.config.cluster.v3.Cluster.CommonLbConfig.ConsistentHashingLbConfig +- 33, // 69: envoy.config.cluster.v3.Cluster.RefreshRate.base_interval:type_name -> google.protobuf.Duration +- 33, // 70: envoy.config.cluster.v3.Cluster.RefreshRate.max_interval:type_name -> google.protobuf.Duration +- 58, // 71: envoy.config.cluster.v3.Cluster.PreconnectPolicy.per_upstream_preconnect_ratio:type_name -> google.protobuf.DoubleValue +- 58, // 72: envoy.config.cluster.v3.Cluster.PreconnectPolicy.predictive_preconnect_ratio:type_name -> google.protobuf.DoubleValue +- 54, // 73: envoy.config.cluster.v3.Cluster.TypedExtensionProtocolOptionsEntry.value:type_name -> google.protobuf.Any +- 5, // 74: envoy.config.cluster.v3.Cluster.LbSubsetConfig.LbSubsetSelector.fallback_policy:type_name -> envoy.config.cluster.v3.Cluster.LbSubsetConfig.LbSubsetSelector.LbSubsetSelectorFallbackPolicy +- 57, // 75: envoy.config.cluster.v3.Cluster.CommonLbConfig.ZoneAwareLbConfig.routing_enabled:type_name -> envoy.type.v3.Percent +- 56, // 76: envoy.config.cluster.v3.Cluster.CommonLbConfig.ZoneAwareLbConfig.min_cluster_size:type_name -> google.protobuf.UInt64Value +- 34, // 77: envoy.config.cluster.v3.Cluster.CommonLbConfig.ConsistentHashingLbConfig.hash_balance_factor:type_name -> google.protobuf.UInt32Value +- 44, // 78: envoy.config.cluster.v3.LoadBalancingPolicy.Policy.typed_extension_config:type_name -> envoy.config.core.v3.TypedExtensionConfig +- 79, // [79:79] is the sub-list for method output_type +- 79, // [79:79] is the sub-list for method input_type +- 79, // [79:79] is the sub-list for extension type_name +- 79, // [79:79] is the sub-list for extension extendee +- 0, // [0:79] is the sub-list for field type_name ++ 56, // 56: envoy.config.cluster.v3.Cluster.SlowStartConfig.min_weight_percent:type_name -> envoy.type.v3.Percent ++ 17, // 57: envoy.config.cluster.v3.Cluster.RoundRobinLbConfig.slow_start_config:type_name -> envoy.config.cluster.v3.Cluster.SlowStartConfig ++ 34, // 58: envoy.config.cluster.v3.Cluster.LeastRequestLbConfig.choice_count:type_name -> google.protobuf.UInt32Value ++ 55, // 59: envoy.config.cluster.v3.Cluster.LeastRequestLbConfig.active_request_bias:type_name -> envoy.config.core.v3.RuntimeDouble ++ 17, // 60: envoy.config.cluster.v3.Cluster.LeastRequestLbConfig.slow_start_config:type_name -> envoy.config.cluster.v3.Cluster.SlowStartConfig ++ 57, // 61: envoy.config.cluster.v3.Cluster.RingHashLbConfig.minimum_ring_size:type_name -> google.protobuf.UInt64Value ++ 6, // 62: envoy.config.cluster.v3.Cluster.RingHashLbConfig.hash_function:type_name -> envoy.config.cluster.v3.Cluster.RingHashLbConfig.HashFunction ++ 57, // 63: envoy.config.cluster.v3.Cluster.RingHashLbConfig.maximum_ring_size:type_name -> google.protobuf.UInt64Value ++ 57, // 64: envoy.config.cluster.v3.Cluster.MaglevLbConfig.table_size:type_name -> google.protobuf.UInt64Value ++ 56, // 65: envoy.config.cluster.v3.Cluster.CommonLbConfig.healthy_panic_threshold:type_name -> envoy.type.v3.Percent ++ 28, // 66: envoy.config.cluster.v3.Cluster.CommonLbConfig.zone_aware_lb_config:type_name -> envoy.config.cluster.v3.Cluster.CommonLbConfig.ZoneAwareLbConfig ++ 29, // 67: envoy.config.cluster.v3.Cluster.CommonLbConfig.locality_weighted_lb_config:type_name -> envoy.config.cluster.v3.Cluster.CommonLbConfig.LocalityWeightedLbConfig ++ 33, // 68: envoy.config.cluster.v3.Cluster.CommonLbConfig.update_merge_window:type_name -> google.protobuf.Duration ++ 30, // 69: envoy.config.cluster.v3.Cluster.CommonLbConfig.consistent_hashing_lb_config:type_name -> envoy.config.cluster.v3.Cluster.CommonLbConfig.ConsistentHashingLbConfig ++ 33, // 70: envoy.config.cluster.v3.Cluster.RefreshRate.base_interval:type_name -> google.protobuf.Duration ++ 33, // 71: envoy.config.cluster.v3.Cluster.RefreshRate.max_interval:type_name -> google.protobuf.Duration ++ 58, // 72: envoy.config.cluster.v3.Cluster.PreconnectPolicy.per_upstream_preconnect_ratio:type_name -> google.protobuf.DoubleValue ++ 58, // 73: envoy.config.cluster.v3.Cluster.PreconnectPolicy.predictive_preconnect_ratio:type_name -> google.protobuf.DoubleValue ++ 54, // 74: envoy.config.cluster.v3.Cluster.TypedExtensionProtocolOptionsEntry.value:type_name -> google.protobuf.Any ++ 5, // 75: envoy.config.cluster.v3.Cluster.LbSubsetConfig.LbSubsetSelector.fallback_policy:type_name -> envoy.config.cluster.v3.Cluster.LbSubsetConfig.LbSubsetSelector.LbSubsetSelectorFallbackPolicy ++ 56, // 76: envoy.config.cluster.v3.Cluster.CommonLbConfig.ZoneAwareLbConfig.routing_enabled:type_name -> envoy.type.v3.Percent ++ 57, // 77: envoy.config.cluster.v3.Cluster.CommonLbConfig.ZoneAwareLbConfig.min_cluster_size:type_name -> google.protobuf.UInt64Value ++ 34, // 78: envoy.config.cluster.v3.Cluster.CommonLbConfig.ConsistentHashingLbConfig.hash_balance_factor:type_name -> google.protobuf.UInt32Value ++ 44, // 79: envoy.config.cluster.v3.LoadBalancingPolicy.Policy.typed_extension_config:type_name -> envoy.config.core.v3.TypedExtensionConfig ++ 80, // [80:80] is the sub-list for method output_type ++ 80, // [80:80] is the sub-list for method input_type ++ 80, // [80:80] is the sub-list for extension type_name ++ 80, // [80:80] is the sub-list for extension extendee ++ 0, // [0:80] is the sub-list for field type_name + } + + func init() { file_envoy_config_cluster_v3_cluster_proto_init() } +diff --git a/envoy/config/cluster/v3/cluster.pb.validate.go b/envoy/config/cluster/v3/cluster.pb.validate.go +index 5d6d5188..8ac8ccbd 100755 +--- a/envoy/config/cluster/v3/cluster.pb.validate.go ++++ b/envoy/config/cluster/v3/cluster.pb.validate.go +@@ -1390,6 +1390,16 @@ func (m *Cluster_SlowStartConfig) Validate() error { + } + } + ++ if v, ok := interface{}(m.GetMinWeightPercent()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return Cluster_SlowStartConfigValidationError{ ++ field: "MinWeightPercent", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ + return nil + } + +diff --git a/envoy/config/route/v3/route.pb.go b/envoy/config/route/v3/route.pb.go +index 2e1f9e6d..89d3cef8 100755 +--- a/envoy/config/route/v3/route.pb.go ++++ b/envoy/config/route/v3/route.pb.go +@@ -111,9 +111,8 @@ type RouteConfiguration struct { + // is not subject to data plane buffering controls. + // + MaxDirectResponseBodySizeBytes *wrappers.UInt32Value `protobuf:"bytes,11,opt,name=max_direct_response_body_size_bytes,json=maxDirectResponseBodySizeBytes,proto3" json:"max_direct_response_body_size_bytes,omitempty"` +- // [#not-implemented-hide:] + // A list of plugins and their configurations which may be used by a +- // :ref:`envoy_v3_api_field_config.route.v3.RouteAction.cluster_specifier_plugin` ++ // :ref:`cluster specifier plugin name ` + // within the route. All *extension.name* fields in this list must be unique. + ClusterSpecifierPlugins []*ClusterSpecifierPlugin `protobuf:"bytes,12,rep,name=cluster_specifier_plugins,json=clusterSpecifierPlugins,proto3" json:"cluster_specifier_plugins,omitempty"` + } +@@ -234,55 +233,6 @@ func (x *RouteConfiguration) GetClusterSpecifierPlugins() []*ClusterSpecifierPlu + return nil + } + +-// Configuration for a cluster specifier plugin. +-type ClusterSpecifierPlugin struct { +- state protoimpl.MessageState +- sizeCache protoimpl.SizeCache +- unknownFields protoimpl.UnknownFields +- +- // The name of the plugin and its opaque configuration. +- Extension *v3.TypedExtensionConfig `protobuf:"bytes,1,opt,name=extension,proto3" json:"extension,omitempty"` +-} +- +-func (x *ClusterSpecifierPlugin) Reset() { +- *x = ClusterSpecifierPlugin{} +- if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_proto_msgTypes[1] +- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) +- ms.StoreMessageInfo(mi) +- } +-} +- +-func (x *ClusterSpecifierPlugin) String() string { +- return protoimpl.X.MessageStringOf(x) +-} +- +-func (*ClusterSpecifierPlugin) ProtoMessage() {} +- +-func (x *ClusterSpecifierPlugin) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_proto_msgTypes[1] +- if protoimpl.UnsafeEnabled && x != nil { +- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) +- if ms.LoadMessageInfo() == nil { +- ms.StoreMessageInfo(mi) +- } +- return ms +- } +- return mi.MessageOf(x) +-} +- +-// Deprecated: Use ClusterSpecifierPlugin.ProtoReflect.Descriptor instead. +-func (*ClusterSpecifierPlugin) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_proto_rawDescGZIP(), []int{1} +-} +- +-func (x *ClusterSpecifierPlugin) GetExtension() *v3.TypedExtensionConfig { +- if x != nil { +- return x.Extension +- } +- return nil +-} +- + type Vhds struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache +@@ -295,7 +245,7 @@ type Vhds struct { + func (x *Vhds) Reset() { + *x = Vhds{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_proto_msgTypes[2] ++ mi := &file_envoy_config_route_v3_route_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -308,7 +258,7 @@ func (x *Vhds) String() string { + func (*Vhds) ProtoMessage() {} + + func (x *Vhds) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_proto_msgTypes[2] ++ mi := &file_envoy_config_route_v3_route_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -321,7 +271,7 @@ func (x *Vhds) ProtoReflect() protoreflect.Message { + + // Deprecated: Use Vhds.ProtoReflect.Descriptor instead. + func (*Vhds) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_proto_rawDescGZIP(), []int{2} ++ return file_envoy_config_route_v3_route_proto_rawDescGZIP(), []int{1} + } + + func (x *Vhds) GetConfigSource() *v3.ConfigSource { +@@ -342,101 +292,92 @@ var file_envoy_config_route_v3_route_proto_rawDesc = []byte{ + 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, 0x65, 0x6e, 0x76, + 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, + 0x33, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x65, 0x78, 0x74, 0x65, +- 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x65, 0x6e, 0x76, +- 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2f, +- 0x76, 0x33, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, +- 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, +- 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x75, 0x64, 0x70, 0x61, 0x2f, +- 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, +- 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, +- 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, +- 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, +- 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xed, 0x07, 0x0a, 0x12, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, +- 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, +- 0x47, 0x0a, 0x0d, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, +- 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x56, +- 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, +- 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x76, 0x68, 0x64, 0x73, +- 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x56, +- 0x68, 0x64, 0x73, 0x52, 0x04, 0x76, 0x68, 0x64, 0x73, 0x12, 0x44, 0x0a, 0x15, 0x69, 0x6e, 0x74, +- 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, +- 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x92, 0x01, 0x0a, +- 0x22, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x13, 0x69, 0x6e, 0x74, 0x65, +- 0x72, 0x6e, 0x61, 0x6c, 0x4f, 0x6e, 0x6c, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, +- 0x69, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, +- 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x64, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, +- 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, +- 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x92, 0x01, +- 0x03, 0x10, 0xe8, 0x07, 0x52, 0x14, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x41, 0x64, 0x64, 0x12, 0x4d, 0x0a, 0x1a, 0x72, 0x65, +- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, +- 0x6f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x42, 0x10, +- 0xfa, 0x42, 0x0d, 0x92, 0x01, 0x0a, 0x22, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, +- 0x52, 0x17, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, +- 0x73, 0x54, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x67, 0x0a, 0x16, 0x72, 0x65, 0x71, +- 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, +- 0x61, 0x64, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, +- 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, +- 0x6f, 0x6e, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x92, 0x01, 0x03, 0x10, 0xe8, 0x07, 0x52, 0x13, 0x72, +- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x41, +- 0x64, 0x64, 0x12, 0x4b, 0x0a, 0x19, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, +- 0x08, 0x20, 0x03, 0x28, 0x09, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x92, 0x01, 0x0a, 0x22, 0x08, 0x72, +- 0x06, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x16, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, +- 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, +- 0x4c, 0x0a, 0x23, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, +- 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, +- 0x73, 0x5f, 0x77, 0x69, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x6d, 0x6f, +- 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, +- 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x57, 0x69, 0x6e, 0x73, 0x12, 0x47, 0x0a, +- 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, +- 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, +- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, +- 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x69, 0x0a, 0x23, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, +- 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x62, 0x6f, +- 0x64, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, +- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, +- 0x65, 0x52, 0x1e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, +- 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, +- 0x73, 0x12, 0x69, 0x0a, 0x19, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, +- 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x0c, +- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, +- 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, +- 0x67, 0x69, 0x6e, 0x52, 0x17, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, +- 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x3a, 0x26, 0x9a, 0xc5, +- 0x88, 0x1e, 0x21, 0x0a, 0x1f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, +- 0x32, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, +- 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x62, 0x0a, 0x16, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, +- 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x48, +- 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, +- 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x65, +- 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x73, 0x0a, 0x04, 0x56, 0x68, 0x64, 0x73, +- 0x12, 0x51, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, +- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, +- 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, +- 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x6f, 0x75, +- 0x72, 0x63, 0x65, 0x3a, 0x18, 0x9a, 0xc5, 0x88, 0x1e, 0x13, 0x0a, 0x11, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x68, 0x64, 0x73, 0x42, 0x3b, 0x0a, +- 0x23, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, +- 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, +- 0x65, 0x2e, 0x76, 0x33, 0x42, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, +- 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, +- 0x6f, 0x33, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, ++ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x1a, 0x21, 0x75, 0x64, 0x70, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, ++ 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2e, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, ++ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xed, ++ 0x07, 0x0a, 0x12, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, ++ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, ++ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x76, 0x69, 0x72, ++ 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, ++ 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, ++ 0x48, 0x6f, 0x73, 0x74, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, ++ 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x76, 0x68, 0x64, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x1b, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x56, 0x68, 0x64, 0x73, 0x52, 0x04, 0x76, ++ 0x68, 0x64, 0x73, 0x12, 0x44, 0x0a, 0x15, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, ++ 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, ++ 0x28, 0x09, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x92, 0x01, 0x0a, 0x22, 0x08, 0x72, 0x06, 0xc0, 0x01, ++ 0x01, 0xc8, 0x01, 0x00, 0x52, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4f, 0x6e, ++ 0x6c, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x69, 0x0a, 0x17, 0x72, 0x65, 0x73, ++ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, ++ 0x5f, 0x61, 0x64, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, ++ 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, ++ 0x69, 0x6f, 0x6e, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x92, 0x01, 0x03, 0x10, 0xe8, 0x07, 0x52, 0x14, ++ 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, ++ 0x6f, 0x41, 0x64, 0x64, 0x12, 0x4d, 0x0a, 0x1a, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, ++ 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, ++ 0x76, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x92, 0x01, 0x0a, ++ 0x22, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x17, 0x72, 0x65, 0x73, 0x70, ++ 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x6d, ++ 0x6f, 0x76, 0x65, 0x12, 0x67, 0x0a, 0x16, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, ++ 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x64, 0x64, 0x18, 0x06, 0x20, ++ 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, ++ 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0xfa, 0x42, ++ 0x06, 0x92, 0x01, 0x03, 0x10, 0xe8, 0x07, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, ++ 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x41, 0x64, 0x64, 0x12, 0x4b, 0x0a, 0x19, ++ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, ++ 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x42, ++ 0x10, 0xfa, 0x42, 0x0d, 0x92, 0x01, 0x0a, 0x22, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x01, 0xc8, 0x01, ++ 0x00, 0x52, 0x16, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, ++ 0x73, 0x54, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x4c, 0x0a, 0x23, 0x6d, 0x6f, 0x73, ++ 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, ++ 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x77, 0x69, 0x6e, 0x73, ++ 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x6d, 0x6f, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, ++ 0x69, 0x66, 0x69, 0x63, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, ++ 0x6f, 0x6e, 0x73, 0x57, 0x69, 0x6e, 0x73, 0x12, 0x47, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, ++ 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x10, ++ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, ++ 0x12, 0x69, 0x0a, 0x23, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, ++ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x73, 0x69, 0x7a, ++ 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, ++ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, ++ 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x1e, 0x6d, 0x61, 0x78, ++ 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6f, ++ 0x64, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x19, 0x63, ++ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, ++ 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, ++ 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, 0x17, 0x63, ++ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, ++ 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x3a, 0x26, 0x9a, 0xc5, 0x88, 0x1e, 0x21, 0x0a, 0x1f, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x6f, 0x75, 0x74, ++ 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x73, ++ 0x0a, 0x04, 0x56, 0x68, 0x64, 0x73, 0x12, 0x51, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, ++ 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x18, 0x9a, 0xc5, 0x88, 0x1e, 0x13, ++ 0x0a, 0x11, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x56, ++ 0x68, 0x64, 0x73, 0x42, 0x3b, 0x0a, 0x23, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, ++ 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x42, 0x0a, 0x52, 0x6f, 0x75, 0x74, ++ 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, 0x10, 0x02, ++ 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +@@ -451,33 +392,31 @@ func file_envoy_config_route_v3_route_proto_rawDescGZIP() []byte { + return file_envoy_config_route_v3_route_proto_rawDescData + } + +-var file_envoy_config_route_v3_route_proto_msgTypes = make([]protoimpl.MessageInfo, 3) ++var file_envoy_config_route_v3_route_proto_msgTypes = make([]protoimpl.MessageInfo, 2) + var file_envoy_config_route_v3_route_proto_goTypes = []interface{}{ +- (*RouteConfiguration)(nil), // 0: envoy.config.route.v3.RouteConfiguration +- (*ClusterSpecifierPlugin)(nil), // 1: envoy.config.route.v3.ClusterSpecifierPlugin +- (*Vhds)(nil), // 2: envoy.config.route.v3.Vhds +- (*VirtualHost)(nil), // 3: envoy.config.route.v3.VirtualHost +- (*v3.HeaderValueOption)(nil), // 4: envoy.config.core.v3.HeaderValueOption +- (*wrappers.BoolValue)(nil), // 5: google.protobuf.BoolValue +- (*wrappers.UInt32Value)(nil), // 6: google.protobuf.UInt32Value +- (*v3.TypedExtensionConfig)(nil), // 7: envoy.config.core.v3.TypedExtensionConfig +- (*v3.ConfigSource)(nil), // 8: envoy.config.core.v3.ConfigSource ++ (*RouteConfiguration)(nil), // 0: envoy.config.route.v3.RouteConfiguration ++ (*Vhds)(nil), // 1: envoy.config.route.v3.Vhds ++ (*VirtualHost)(nil), // 2: envoy.config.route.v3.VirtualHost ++ (*v3.HeaderValueOption)(nil), // 3: envoy.config.core.v3.HeaderValueOption ++ (*wrappers.BoolValue)(nil), // 4: google.protobuf.BoolValue ++ (*wrappers.UInt32Value)(nil), // 5: google.protobuf.UInt32Value ++ (*ClusterSpecifierPlugin)(nil), // 6: envoy.config.route.v3.ClusterSpecifierPlugin ++ (*v3.ConfigSource)(nil), // 7: envoy.config.core.v3.ConfigSource + } + var file_envoy_config_route_v3_route_proto_depIdxs = []int32{ +- 3, // 0: envoy.config.route.v3.RouteConfiguration.virtual_hosts:type_name -> envoy.config.route.v3.VirtualHost +- 2, // 1: envoy.config.route.v3.RouteConfiguration.vhds:type_name -> envoy.config.route.v3.Vhds +- 4, // 2: envoy.config.route.v3.RouteConfiguration.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 4, // 3: envoy.config.route.v3.RouteConfiguration.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 5, // 4: envoy.config.route.v3.RouteConfiguration.validate_clusters:type_name -> google.protobuf.BoolValue +- 6, // 5: envoy.config.route.v3.RouteConfiguration.max_direct_response_body_size_bytes:type_name -> google.protobuf.UInt32Value +- 1, // 6: envoy.config.route.v3.RouteConfiguration.cluster_specifier_plugins:type_name -> envoy.config.route.v3.ClusterSpecifierPlugin +- 7, // 7: envoy.config.route.v3.ClusterSpecifierPlugin.extension:type_name -> envoy.config.core.v3.TypedExtensionConfig +- 8, // 8: envoy.config.route.v3.Vhds.config_source:type_name -> envoy.config.core.v3.ConfigSource +- 9, // [9:9] is the sub-list for method output_type +- 9, // [9:9] is the sub-list for method input_type +- 9, // [9:9] is the sub-list for extension type_name +- 9, // [9:9] is the sub-list for extension extendee +- 0, // [0:9] is the sub-list for field type_name ++ 2, // 0: envoy.config.route.v3.RouteConfiguration.virtual_hosts:type_name -> envoy.config.route.v3.VirtualHost ++ 1, // 1: envoy.config.route.v3.RouteConfiguration.vhds:type_name -> envoy.config.route.v3.Vhds ++ 3, // 2: envoy.config.route.v3.RouteConfiguration.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 3, // 3: envoy.config.route.v3.RouteConfiguration.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 4, // 4: envoy.config.route.v3.RouteConfiguration.validate_clusters:type_name -> google.protobuf.BoolValue ++ 5, // 5: envoy.config.route.v3.RouteConfiguration.max_direct_response_body_size_bytes:type_name -> google.protobuf.UInt32Value ++ 6, // 6: envoy.config.route.v3.RouteConfiguration.cluster_specifier_plugins:type_name -> envoy.config.route.v3.ClusterSpecifierPlugin ++ 7, // 7: envoy.config.route.v3.Vhds.config_source:type_name -> envoy.config.core.v3.ConfigSource ++ 8, // [8:8] is the sub-list for method output_type ++ 8, // [8:8] is the sub-list for method input_type ++ 8, // [8:8] is the sub-list for extension type_name ++ 8, // [8:8] is the sub-list for extension extendee ++ 0, // [0:8] is the sub-list for field type_name + } + + func init() { file_envoy_config_route_v3_route_proto_init() } +@@ -500,18 +439,6 @@ func file_envoy_config_route_v3_route_proto_init() { + } + } + file_envoy_config_route_v3_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*ClusterSpecifierPlugin); i { +- case 0: +- return &v.state +- case 1: +- return &v.sizeCache +- case 2: +- return &v.unknownFields +- default: +- return nil +- } +- } +- file_envoy_config_route_v3_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Vhds); i { + case 0: + return &v.state +@@ -530,7 +457,7 @@ func file_envoy_config_route_v3_route_proto_init() { + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_envoy_config_route_v3_route_proto_rawDesc, + NumEnums: 0, +- NumMessages: 3, ++ NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, +diff --git a/envoy/config/route/v3/route.pb.validate.go b/envoy/config/route/v3/route.pb.validate.go +index 11be46ca..5bb91f7d 100755 +--- a/envoy/config/route/v3/route.pb.validate.go ++++ b/envoy/config/route/v3/route.pb.validate.go +@@ -250,83 +250,6 @@ var _RouteConfiguration_ResponseHeadersToRemove_Pattern = regexp.MustCompile("^[ + + var _RouteConfiguration_RequestHeadersToRemove_Pattern = regexp.MustCompile("^[^\x00\n\r]*$") + +-// Validate checks the field values on ClusterSpecifierPlugin with the rules +-// defined in the proto definition for this message. If any rules are +-// violated, an error is returned. +-func (m *ClusterSpecifierPlugin) Validate() error { +- if m == nil { +- return nil +- } +- +- if v, ok := interface{}(m.GetExtension()).(interface{ Validate() error }); ok { +- if err := v.Validate(); err != nil { +- return ClusterSpecifierPluginValidationError{ +- field: "Extension", +- reason: "embedded message failed validation", +- cause: err, +- } +- } +- } +- +- return nil +-} +- +-// ClusterSpecifierPluginValidationError is the validation error returned by +-// ClusterSpecifierPlugin.Validate if the designated constraints aren't met. +-type ClusterSpecifierPluginValidationError struct { +- field string +- reason string +- cause error +- key bool +-} +- +-// Field function returns field value. +-func (e ClusterSpecifierPluginValidationError) Field() string { return e.field } +- +-// Reason function returns reason value. +-func (e ClusterSpecifierPluginValidationError) Reason() string { return e.reason } +- +-// Cause function returns cause value. +-func (e ClusterSpecifierPluginValidationError) Cause() error { return e.cause } +- +-// Key function returns key value. +-func (e ClusterSpecifierPluginValidationError) Key() bool { return e.key } +- +-// ErrorName returns error name. +-func (e ClusterSpecifierPluginValidationError) ErrorName() string { +- return "ClusterSpecifierPluginValidationError" +-} +- +-// Error satisfies the builtin error interface +-func (e ClusterSpecifierPluginValidationError) Error() string { +- cause := "" +- if e.cause != nil { +- cause = fmt.Sprintf(" | caused by: %v", e.cause) +- } +- +- key := "" +- if e.key { +- key = "key for " +- } +- +- return fmt.Sprintf( +- "invalid %sClusterSpecifierPlugin.%s: %s%s", +- key, +- e.field, +- e.reason, +- cause) +-} +- +-var _ error = ClusterSpecifierPluginValidationError{} +- +-var _ interface { +- Field() string +- Reason() string +- Key() bool +- Cause() error +- ErrorName() string +-} = ClusterSpecifierPluginValidationError{} +- + // Validate checks the field values on Vhds with the rules defined in the proto + // definition for this message. If any rules are violated, an error is returned. + func (m *Vhds) Validate() error { +diff --git a/envoy/config/route/v3/route_components.pb.go b/envoy/config/route/v3/route_components.pb.go +index 71444557..61cf9f93 100755 +--- a/envoy/config/route/v3/route_components.pb.go ++++ b/envoy/config/route/v3/route_components.pb.go +@@ -135,7 +135,7 @@ func (x RouteAction_ClusterNotFoundResponseCode) Number() protoreflect.EnumNumbe + + // Deprecated: Use RouteAction_ClusterNotFoundResponseCode.Descriptor instead. + func (RouteAction_ClusterNotFoundResponseCode) EnumDescriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 0} + } + + // Configures :ref:`internal redirect ` behavior. +@@ -185,7 +185,7 @@ func (x RouteAction_InternalRedirectAction) Number() protoreflect.EnumNumber { + + // Deprecated: Use RouteAction_InternalRedirectAction.Descriptor instead. + func (RouteAction_InternalRedirectAction) EnumDescriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 1} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1} + } + + type RetryPolicy_ResetHeaderFormat int32 +@@ -231,7 +231,7 @@ func (x RetryPolicy_ResetHeaderFormat) Number() protoreflect.EnumNumber { + + // Deprecated: Use RetryPolicy_ResetHeaderFormat.Descriptor instead. + func (RetryPolicy_ResetHeaderFormat) EnumDescriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8, 0} + } + + type RedirectAction_RedirectResponseCode int32 +@@ -291,7 +291,7 @@ func (x RedirectAction_RedirectResponseCode) Number() protoreflect.EnumNumber { + + // Deprecated: Use RedirectAction_RedirectResponseCode.Descriptor instead. + func (RedirectAction_RedirectResponseCode) EnumDescriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{9, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{10, 0} + } + + type RateLimit_Action_MetaData_Source int32 +@@ -339,7 +339,7 @@ func (x RateLimit_Action_MetaData_Source) Number() protoreflect.EnumNumber { + + // Deprecated: Use RateLimit_Action_MetaData_Source.Descriptor instead. + func (RateLimit_Action_MetaData_Source) EnumDescriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 7, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 7, 0} + } + + // The top level element in the routing configuration is a virtual host. Each virtual host has +@@ -956,6 +956,14 @@ type WeightedCluster struct { + // configuration file will be used as the default weight. See the :ref:`runtime documentation + // ` for how key names map to the underlying implementation. + RuntimeKeyPrefix string `protobuf:"bytes,2,opt,name=runtime_key_prefix,json=runtimeKeyPrefix,proto3" json:"runtime_key_prefix,omitempty"` ++ // Name of the cluster specifier plugin to use to determine the cluster for requests on this route. ++ // The cluster specifier plugin name must be defined in the associated ++ // :ref:`cluster specifier plugins ` ++ // in the :ref:`name ` field. ++ ClusterSpecifierPlugin string `protobuf:"bytes,100,opt,name=cluster_specifier_plugin,json=clusterSpecifierPlugin,proto3" json:"cluster_specifier_plugin,omitempty"` ++ // Custom cluster specifier plugin configuration to use to determine the cluster for requests ++ // on this route. ++ InlineClusterSpecifierPlugin *ClusterSpecifierPlugin `protobuf:"bytes,101,opt,name=inline_cluster_specifier_plugin,json=inlineClusterSpecifierPlugin,proto3" json:"inline_cluster_specifier_plugin,omitempty"` + } + + func (x *WeightedCluster) Reset() { +@@ -1011,7 +1019,83 @@ func (x *WeightedCluster) GetRuntimeKeyPrefix() string { + return "" + } + +-// [#next-free-field: 14] ++func (x *WeightedCluster) GetClusterSpecifierPlugin() string { ++ if x != nil { ++ return x.ClusterSpecifierPlugin ++ } ++ return "" ++} ++ ++func (x *WeightedCluster) GetInlineClusterSpecifierPlugin() *ClusterSpecifierPlugin { ++ if x != nil { ++ return x.InlineClusterSpecifierPlugin ++ } ++ return nil ++} ++ ++// Configuration for a cluster specifier plugin. ++type ClusterSpecifierPlugin struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ // The name of the plugin and its opaque configuration. ++ Extension *v3.TypedExtensionConfig `protobuf:"bytes,1,opt,name=extension,proto3" json:"extension,omitempty"` ++ // If is_optional is not set or is set to false and the plugin defined by this message is not a ++ // supported type, the containing resource is NACKed. If is_optional is set to true, the resource ++ // would not be NACKed for this reason. In this case, routes referencing this plugin's name would ++ // not be treated as an illegal configuration, but would result in a failure if the route is ++ // selected. ++ IsOptional bool `protobuf:"varint,2,opt,name=is_optional,json=isOptional,proto3" json:"is_optional,omitempty"` ++} ++ ++func (x *ClusterSpecifierPlugin) Reset() { ++ *x = ClusterSpecifierPlugin{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[4] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *ClusterSpecifierPlugin) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*ClusterSpecifierPlugin) ProtoMessage() {} ++ ++func (x *ClusterSpecifierPlugin) ProtoReflect() protoreflect.Message { ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[4] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use ClusterSpecifierPlugin.ProtoReflect.Descriptor instead. ++func (*ClusterSpecifierPlugin) Descriptor() ([]byte, []int) { ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{4} ++} ++ ++func (x *ClusterSpecifierPlugin) GetExtension() *v3.TypedExtensionConfig { ++ if x != nil { ++ return x.Extension ++ } ++ return nil ++} ++ ++func (x *ClusterSpecifierPlugin) GetIsOptional() bool { ++ if x != nil { ++ return x.IsOptional ++ } ++ return false ++} ++ ++// [#next-free-field: 15] + type RouteMatch struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache +@@ -1082,7 +1166,7 @@ type RouteMatch struct { + func (x *RouteMatch) Reset() { + *x = RouteMatch{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[4] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -1095,7 +1179,7 @@ func (x *RouteMatch) String() string { + func (*RouteMatch) ProtoMessage() {} + + func (x *RouteMatch) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[4] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -1108,7 +1192,7 @@ func (x *RouteMatch) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteMatch.ProtoReflect.Descriptor instead. + func (*RouteMatch) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{4} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{5} + } + + func (m *RouteMatch) GetPathSpecifier() isRouteMatch_PathSpecifier { +@@ -1285,7 +1369,7 @@ type CorsPolicy struct { + func (x *CorsPolicy) Reset() { + *x = CorsPolicy{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[5] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -1298,7 +1382,7 @@ func (x *CorsPolicy) String() string { + func (*CorsPolicy) ProtoMessage() {} + + func (x *CorsPolicy) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[5] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -1311,7 +1395,7 @@ func (x *CorsPolicy) ProtoReflect() protoreflect.Message { + + // Deprecated: Use CorsPolicy.ProtoReflect.Descriptor instead. + func (*CorsPolicy) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{5} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6} + } + + func (x *CorsPolicy) GetAllowOriginStringMatch() []*v31.StringMatcher { +@@ -1394,7 +1478,7 @@ type CorsPolicy_FilterEnabled struct { + + func (*CorsPolicy_FilterEnabled) isCorsPolicy_EnabledSpecifier() {} + +-// [#next-free-field: 38] ++// [#next-free-field: 40] + type RouteAction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache +@@ -1405,6 +1489,7 @@ type RouteAction struct { + // *RouteAction_ClusterHeader + // *RouteAction_WeightedClusters + // *RouteAction_ClusterSpecifierPlugin ++ // *RouteAction_InlineClusterSpecifierPlugin + ClusterSpecifier isRouteAction_ClusterSpecifier `protobuf_oneof:"cluster_specifier"` + // The HTTP status code to use when configured cluster is not found. + // The default response code is 503 Service Unavailable. +@@ -1622,13 +1707,14 @@ type RouteAction struct { + // (e.g.: policies are not merged, most internal one becomes the enforced policy). + HedgePolicy *HedgePolicy `protobuf:"bytes,27,opt,name=hedge_policy,json=hedgePolicy,proto3" json:"hedge_policy,omitempty"` + // Specifies the maximum stream duration for this route. +- MaxStreamDuration *RouteAction_MaxStreamDuration `protobuf:"bytes,36,opt,name=max_stream_duration,json=maxStreamDuration,proto3" json:"max_stream_duration,omitempty"` ++ MaxStreamDuration *RouteAction_MaxStreamDuration `protobuf:"bytes,36,opt,name=max_stream_duration,json=maxStreamDuration,proto3" json:"max_stream_duration,omitempty"` ++ InternalActiveRedirectPolicy *InternalActiveRedirectPolicy `protobuf:"bytes,1000,opt,name=internal_active_redirect_policy,json=internalActiveRedirectPolicy,proto3" json:"internal_active_redirect_policy,omitempty"` + } + + func (x *RouteAction) Reset() { + *x = RouteAction{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[6] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -1641,7 +1727,7 @@ func (x *RouteAction) String() string { + func (*RouteAction) ProtoMessage() {} + + func (x *RouteAction) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[6] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -1654,7 +1740,7 @@ func (x *RouteAction) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteAction.ProtoReflect.Descriptor instead. + func (*RouteAction) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7} + } + + func (m *RouteAction) GetClusterSpecifier() isRouteAction_ClusterSpecifier { +@@ -1692,6 +1778,13 @@ func (x *RouteAction) GetClusterSpecifierPlugin() string { + return "" + } + ++func (x *RouteAction) GetInlineClusterSpecifierPlugin() *ClusterSpecifierPlugin { ++ if x, ok := x.GetClusterSpecifier().(*RouteAction_InlineClusterSpecifierPlugin); ok { ++ return x.InlineClusterSpecifierPlugin ++ } ++ return nil ++} ++ + func (x *RouteAction) GetClusterNotFoundResponseCode() RouteAction_ClusterNotFoundResponseCode { + if x != nil { + return x.ClusterNotFoundResponseCode +@@ -1886,6 +1979,13 @@ func (x *RouteAction) GetMaxStreamDuration() *RouteAction_MaxStreamDuration { + return nil + } + ++func (x *RouteAction) GetInternalActiveRedirectPolicy() *InternalActiveRedirectPolicy { ++ if x != nil { ++ return x.InternalActiveRedirectPolicy ++ } ++ return nil ++} ++ + type isRouteAction_ClusterSpecifier interface { + isRouteAction_ClusterSpecifier() + } +@@ -1923,15 +2023,19 @@ type RouteAction_WeightedClusters struct { + } + + type RouteAction_ClusterSpecifierPlugin struct { +- // [#not-implemented-hide:] +- // Name of the cluster specifier plugin to use to determine the cluster for +- // requests on this route. The plugin name must be defined in the associated +- // :ref:`envoy_v3_api_field_config.route.v3.RouteConfiguration.cluster_specifier_plugins` +- // in the +- // :ref:`envoy_v3_api_field_config.core.v3.TypedExtensionConfig.name` field. ++ // Name of the cluster specifier plugin to use to determine the cluster for requests on this route. ++ // The cluster specifier plugin name must be defined in the associated ++ // :ref:`cluster specifier plugins ` ++ // in the :ref:`name ` field. + ClusterSpecifierPlugin string `protobuf:"bytes,37,opt,name=cluster_specifier_plugin,json=clusterSpecifierPlugin,proto3,oneof"` + } + ++type RouteAction_InlineClusterSpecifierPlugin struct { ++ // Custom cluster specifier plugin configuration to use to determine the cluster for requests ++ // on this route. ++ InlineClusterSpecifierPlugin *ClusterSpecifierPlugin `protobuf:"bytes,39,opt,name=inline_cluster_specifier_plugin,json=inlineClusterSpecifierPlugin,proto3,oneof"` ++} ++ + func (*RouteAction_Cluster) isRouteAction_ClusterSpecifier() {} + + func (*RouteAction_ClusterHeader) isRouteAction_ClusterSpecifier() {} +@@ -1940,6 +2044,8 @@ func (*RouteAction_WeightedClusters) isRouteAction_ClusterSpecifier() {} + + func (*RouteAction_ClusterSpecifierPlugin) isRouteAction_ClusterSpecifier() {} + ++func (*RouteAction_InlineClusterSpecifierPlugin) isRouteAction_ClusterSpecifier() {} ++ + type isRouteAction_HostRewriteSpecifier interface { + isRouteAction_HostRewriteSpecifier() + } +@@ -2093,7 +2199,7 @@ type RetryPolicy struct { + func (x *RetryPolicy) Reset() { + *x = RetryPolicy{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[7] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2106,7 +2212,7 @@ func (x *RetryPolicy) String() string { + func (*RetryPolicy) ProtoMessage() {} + + func (x *RetryPolicy) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[7] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2119,7 +2225,7 @@ func (x *RetryPolicy) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RetryPolicy.ProtoReflect.Descriptor instead. + func (*RetryPolicy) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8} + } + + func (x *RetryPolicy) GetRetryOn() string { +@@ -2248,7 +2354,7 @@ type HedgePolicy struct { + func (x *HedgePolicy) Reset() { + *x = HedgePolicy{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[8] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2261,7 +2367,7 @@ func (x *HedgePolicy) String() string { + func (*HedgePolicy) ProtoMessage() {} + + func (x *HedgePolicy) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[8] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2274,7 +2380,7 @@ func (x *HedgePolicy) ProtoReflect() protoreflect.Message { + + // Deprecated: Use HedgePolicy.ProtoReflect.Descriptor instead. + func (*HedgePolicy) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{9} + } + + func (x *HedgePolicy) GetInitialRequests() *wrappers.UInt32Value { +@@ -2334,7 +2440,7 @@ type RedirectAction struct { + func (x *RedirectAction) Reset() { + *x = RedirectAction{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[9] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2347,7 +2453,7 @@ func (x *RedirectAction) String() string { + func (*RedirectAction) ProtoMessage() {} + + func (x *RedirectAction) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[9] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2360,7 +2466,7 @@ func (x *RedirectAction) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RedirectAction.ProtoReflect.Descriptor instead. + func (*RedirectAction) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{9} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{10} + } + + func (m *RedirectAction) GetSchemeRewriteSpecifier() isRedirectAction_SchemeRewriteSpecifier { +@@ -2548,7 +2654,7 @@ type DirectResponseAction struct { + func (x *DirectResponseAction) Reset() { + *x = DirectResponseAction{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[10] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2561,7 +2667,7 @@ func (x *DirectResponseAction) String() string { + func (*DirectResponseAction) ProtoMessage() {} + + func (x *DirectResponseAction) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[10] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2574,7 +2680,7 @@ func (x *DirectResponseAction) ProtoReflect() protoreflect.Message { + + // Deprecated: Use DirectResponseAction.ProtoReflect.Descriptor instead. + func (*DirectResponseAction) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{10} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{11} + } + + func (x *DirectResponseAction) GetStatus() uint32 { +@@ -2601,7 +2707,7 @@ type NonForwardingAction struct { + func (x *NonForwardingAction) Reset() { + *x = NonForwardingAction{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[11] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2614,7 +2720,7 @@ func (x *NonForwardingAction) String() string { + func (*NonForwardingAction) ProtoMessage() {} + + func (x *NonForwardingAction) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[11] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2627,7 +2733,7 @@ func (x *NonForwardingAction) ProtoReflect() protoreflect.Message { + + // Deprecated: Use NonForwardingAction.ProtoReflect.Descriptor instead. + func (*NonForwardingAction) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{11} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{12} + } + + type Decorator struct { +@@ -2651,7 +2757,7 @@ type Decorator struct { + func (x *Decorator) Reset() { + *x = Decorator{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[12] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2664,7 +2770,7 @@ func (x *Decorator) String() string { + func (*Decorator) ProtoMessage() {} + + func (x *Decorator) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[12] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2677,7 +2783,7 @@ func (x *Decorator) ProtoReflect() protoreflect.Message { + + // Deprecated: Use Decorator.ProtoReflect.Descriptor instead. + func (*Decorator) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{12} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{13} + } + + func (x *Decorator) GetOperation() string { +@@ -2733,7 +2839,7 @@ type Tracing struct { + func (x *Tracing) Reset() { + *x = Tracing{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[13] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2746,7 +2852,7 @@ func (x *Tracing) String() string { + func (*Tracing) ProtoMessage() {} + + func (x *Tracing) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[13] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2759,7 +2865,7 @@ func (x *Tracing) ProtoReflect() protoreflect.Message { + + // Deprecated: Use Tracing.ProtoReflect.Descriptor instead. + func (*Tracing) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{13} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{14} + } + + func (x *Tracing) GetClientSampling() *v32.FractionalPercent { +@@ -2825,7 +2931,7 @@ type VirtualCluster struct { + func (x *VirtualCluster) Reset() { + *x = VirtualCluster{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[14] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2838,7 +2944,7 @@ func (x *VirtualCluster) String() string { + func (*VirtualCluster) ProtoMessage() {} + + func (x *VirtualCluster) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[14] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2851,7 +2957,7 @@ func (x *VirtualCluster) ProtoReflect() protoreflect.Message { + + // Deprecated: Use VirtualCluster.ProtoReflect.Descriptor instead. + func (*VirtualCluster) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{14} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15} + } + + func (x *VirtualCluster) GetHeaders() []*HeaderMatcher { +@@ -2902,7 +3008,7 @@ type RateLimit struct { + func (x *RateLimit) Reset() { + *x = RateLimit{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[15] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -2915,7 +3021,7 @@ func (x *RateLimit) String() string { + func (*RateLimit) ProtoMessage() {} + + func (x *RateLimit) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[15] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -2928,7 +3034,7 @@ func (x *RateLimit) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit.ProtoReflect.Descriptor instead. + func (*RateLimit) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16} + } + + func (x *RateLimit) GetStage() *wrappers.UInt32Value { +@@ -3015,7 +3121,7 @@ type HeaderMatcher struct { + func (x *HeaderMatcher) Reset() { + *x = HeaderMatcher{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[16] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3028,7 +3134,7 @@ func (x *HeaderMatcher) String() string { + func (*HeaderMatcher) ProtoMessage() {} + + func (x *HeaderMatcher) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[16] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3041,7 +3147,7 @@ func (x *HeaderMatcher) ProtoReflect() protoreflect.Message { + + // Deprecated: Use HeaderMatcher.ProtoReflect.Descriptor instead. + func (*HeaderMatcher) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{17} + } + + func (x *HeaderMatcher) GetName() string { +@@ -3250,7 +3356,7 @@ type QueryParameterMatcher struct { + func (x *QueryParameterMatcher) Reset() { + *x = QueryParameterMatcher{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[17] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3263,7 +3369,7 @@ func (x *QueryParameterMatcher) String() string { + func (*QueryParameterMatcher) ProtoMessage() {} + + func (x *QueryParameterMatcher) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[17] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3276,7 +3382,7 @@ func (x *QueryParameterMatcher) ProtoReflect() protoreflect.Message { + + // Deprecated: Use QueryParameterMatcher.ProtoReflect.Descriptor instead. + func (*QueryParameterMatcher) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{17} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{18} + } + + func (x *QueryParameterMatcher) GetName() string { +@@ -3357,7 +3463,7 @@ type InternalRedirectPolicy struct { + func (x *InternalRedirectPolicy) Reset() { + *x = InternalRedirectPolicy{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[18] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3370,7 +3476,7 @@ func (x *InternalRedirectPolicy) String() string { + func (*InternalRedirectPolicy) ProtoMessage() {} + + func (x *InternalRedirectPolicy) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[18] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3383,7 +3489,7 @@ func (x *InternalRedirectPolicy) ProtoReflect() protoreflect.Message { + + // Deprecated: Use InternalRedirectPolicy.ProtoReflect.Descriptor instead. + func (*InternalRedirectPolicy) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{18} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{19} + } + + func (x *InternalRedirectPolicy) GetMaxInternalRedirects() *wrappers.UInt32Value { +@@ -3414,43 +3520,67 @@ func (x *InternalRedirectPolicy) GetAllowCrossSchemeRedirect() bool { + return false + } + +-// A simple wrapper for an HTTP filter config. This is intended to be used as a wrapper for the +-// map value in +-// :ref:`VirtualHost.typed_per_filter_config`, +-// :ref:`Route.typed_per_filter_config`, +-// or :ref:`WeightedCluster.ClusterWeight.typed_per_filter_config` +-// to add additional flags to the filter. +-// [#not-implemented-hide:] +-type FilterConfig struct { ++// Redirects to the specified URI based on the response code. ++// [#next-free-field: 19] ++type InternalActiveRedirectPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + +- // The filter config. +- Config *any.Any `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` +- // If true, the filter is optional, meaning that if the client does +- // not support the specified filter, it may ignore the map entry rather +- // than rejecting the config. +- IsOptional bool `protobuf:"varint,2,opt,name=is_optional,json=isOptional,proto3" json:"is_optional,omitempty"` ++ // An internal redirect is not handled, unless the number of previous internal redirects that a ++ // downstream request has encountered is lower than this value. ++ // In the case where a downstream request is bounced among multiple routes by internal redirect, ++ // the first route that hits this threshold, or does not set :ref:`internal_redirect_policy ++ // ` ++ // will pass the redirect back to downstream. ++ // ++ // If not specified, at most one redirect will be followed. ++ MaxInternalRedirects *wrappers.UInt32Value `protobuf:"bytes,1,opt,name=max_internal_redirects,json=maxInternalRedirects,proto3" json:"max_internal_redirects,omitempty"` ++ // Defines what upstream response codes are allowed to trigger internal redirect. ++ // All response codes support redirection except 200. ++ RedirectResponseCodes []uint32 `protobuf:"varint,2,rep,packed,name=redirect_response_codes,json=redirectResponseCodes,proto3" json:"redirect_response_codes,omitempty"` ++ // The URI of the redirect. ++ // ++ // Types that are assignable to RedirectUrlRewriteSpecifier: ++ // *InternalActiveRedirectPolicy_RedirectUrl ++ // *InternalActiveRedirectPolicy_RedirectUrlRewriteRegex ++ RedirectUrlRewriteSpecifier isInternalActiveRedirectPolicy_RedirectUrlRewriteSpecifier `protobuf_oneof:"redirect_url_rewrite_specifier"` ++ // Specifies a list of predicates that are queried when an upstream response is deemed ++ // to trigger an internal redirect by all other criteria. Any predicate in the list can reject ++ // the redirect, causing the response to be proxied to downstream. ++ Predicates []*v3.TypedExtensionConfig `protobuf:"bytes,4,rep,name=predicates,proto3" json:"predicates,omitempty"` ++ // Allow internal redirect to follow a target URI with a different scheme than the value of ++ // x-forwarded-proto. The default is false. ++ AllowCrossSchemeRedirect bool `protobuf:"varint,5,opt,name=allow_cross_scheme_redirect,json=allowCrossSchemeRedirect,proto3" json:"allow_cross_scheme_redirect,omitempty"` ++ // HTTP headers to add to a local reply. This allows the response mapper to append, to add ++ // or to override headers of any local reply before it is sent to a downstream client. ++ RequestHeadersToAdd []*v3.HeaderValueOption `protobuf:"bytes,6,rep,name=request_headers_to_add,json=requestHeadersToAdd,proto3" json:"request_headers_to_add,omitempty"` ++ // Indicates that during forwarding, the host header will be swapped with ++ // this value. ++ HostRewriteLiteral string `protobuf:"bytes,9,opt,name=host_rewrite_literal,json=hostRewriteLiteral,proto3" json:"host_rewrite_literal,omitempty"` ++ // If true, the host name in the downstream request is used for redirection. ++ ForcedUseOriginalHost bool `protobuf:"varint,19,opt,name=forced_use_original_host,json=forcedUseOriginalHost,proto3" json:"forced_use_original_host,omitempty"` ++ ForcedAddHeaderBeforeRouteMatcher bool `protobuf:"varint,21,opt,name=forced_add_header_before_route_matcher,json=forcedAddHeaderBeforeRouteMatcher,proto3" json:"forced_add_header_before_route_matcher,omitempty"` ++ Policies []*InternalActiveRedirectPolicy_RedirectPolicy `protobuf:"bytes,18,rep,name=policies,proto3" json:"policies,omitempty"` + } + +-func (x *FilterConfig) Reset() { +- *x = FilterConfig{} ++func (x *InternalActiveRedirectPolicy) Reset() { ++ *x = InternalActiveRedirectPolicy{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[19] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } + } + +-func (x *FilterConfig) String() string { ++func (x *InternalActiveRedirectPolicy) String() string { + return protoimpl.X.MessageStringOf(x) + } + +-func (*FilterConfig) ProtoMessage() {} ++func (*InternalActiveRedirectPolicy) ProtoMessage() {} + +-func (x *FilterConfig) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[19] ++func (x *InternalActiveRedirectPolicy) ProtoReflect() protoreflect.Message { ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3461,42 +3591,196 @@ func (x *FilterConfig) ProtoReflect() protoreflect.Message { + return mi.MessageOf(x) + } + +-// Deprecated: Use FilterConfig.ProtoReflect.Descriptor instead. +-func (*FilterConfig) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{19} ++// Deprecated: Use InternalActiveRedirectPolicy.ProtoReflect.Descriptor instead. ++func (*InternalActiveRedirectPolicy) Descriptor() ([]byte, []int) { ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{20} + } + +-func (x *FilterConfig) GetConfig() *any.Any { ++func (x *InternalActiveRedirectPolicy) GetMaxInternalRedirects() *wrappers.UInt32Value { + if x != nil { +- return x.Config ++ return x.MaxInternalRedirects + } + return nil + } + +-func (x *FilterConfig) GetIsOptional() bool { ++func (x *InternalActiveRedirectPolicy) GetRedirectResponseCodes() []uint32 { + if x != nil { +- return x.IsOptional ++ return x.RedirectResponseCodes ++ } ++ return nil ++} ++ ++func (m *InternalActiveRedirectPolicy) GetRedirectUrlRewriteSpecifier() isInternalActiveRedirectPolicy_RedirectUrlRewriteSpecifier { ++ if m != nil { ++ return m.RedirectUrlRewriteSpecifier ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy) GetRedirectUrl() string { ++ if x, ok := x.GetRedirectUrlRewriteSpecifier().(*InternalActiveRedirectPolicy_RedirectUrl); ok { ++ return x.RedirectUrl ++ } ++ return "" ++} ++ ++func (x *InternalActiveRedirectPolicy) GetRedirectUrlRewriteRegex() *v31.RegexMatchAndSubstitute { ++ if x, ok := x.GetRedirectUrlRewriteSpecifier().(*InternalActiveRedirectPolicy_RedirectUrlRewriteRegex); ok { ++ return x.RedirectUrlRewriteRegex ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy) GetPredicates() []*v3.TypedExtensionConfig { ++ if x != nil { ++ return x.Predicates ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy) GetAllowCrossSchemeRedirect() bool { ++ if x != nil { ++ return x.AllowCrossSchemeRedirect + } + return false + } + +-// [#next-free-field: 13] +-type WeightedCluster_ClusterWeight struct { +- state protoimpl.MessageState +- sizeCache protoimpl.SizeCache +- unknownFields protoimpl.UnknownFields ++func (x *InternalActiveRedirectPolicy) GetRequestHeadersToAdd() []*v3.HeaderValueOption { ++ if x != nil { ++ return x.RequestHeadersToAdd ++ } ++ return nil ++} + +- // Only one of *name* and *cluster_header* may be specified. +- // [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1}] +- // Name of the upstream cluster. The cluster must exist in the +- // :ref:`cluster manager configuration `. +- Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +- // Only one of *name* and *cluster_header* may be specified. +- // [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1 }] +- // Envoy will determine the cluster to route to by reading the value of the +- // HTTP header named by cluster_header from the request headers. If the +- // header is not found or the referenced cluster does not exist, Envoy will +- // return a 404 response. ++func (x *InternalActiveRedirectPolicy) GetHostRewriteLiteral() string { ++ if x != nil { ++ return x.HostRewriteLiteral ++ } ++ return "" ++} ++ ++func (x *InternalActiveRedirectPolicy) GetForcedUseOriginalHost() bool { ++ if x != nil { ++ return x.ForcedUseOriginalHost ++ } ++ return false ++} ++ ++func (x *InternalActiveRedirectPolicy) GetForcedAddHeaderBeforeRouteMatcher() bool { ++ if x != nil { ++ return x.ForcedAddHeaderBeforeRouteMatcher ++ } ++ return false ++} ++ ++func (x *InternalActiveRedirectPolicy) GetPolicies() []*InternalActiveRedirectPolicy_RedirectPolicy { ++ if x != nil { ++ return x.Policies ++ } ++ return nil ++} ++ ++type isInternalActiveRedirectPolicy_RedirectUrlRewriteSpecifier interface { ++ isInternalActiveRedirectPolicy_RedirectUrlRewriteSpecifier() ++} ++ ++type InternalActiveRedirectPolicy_RedirectUrl struct { ++ RedirectUrl string `protobuf:"bytes,7,opt,name=redirect_url,json=redirectUrl,proto3,oneof"` ++} ++ ++type InternalActiveRedirectPolicy_RedirectUrlRewriteRegex struct { ++ RedirectUrlRewriteRegex *v31.RegexMatchAndSubstitute `protobuf:"bytes,8,opt,name=redirect_url_rewrite_regex,json=redirectUrlRewriteRegex,proto3,oneof"` ++} ++ ++func (*InternalActiveRedirectPolicy_RedirectUrl) isInternalActiveRedirectPolicy_RedirectUrlRewriteSpecifier() { ++} ++ ++func (*InternalActiveRedirectPolicy_RedirectUrlRewriteRegex) isInternalActiveRedirectPolicy_RedirectUrlRewriteSpecifier() { ++} ++ ++// A simple wrapper for an HTTP filter config. This is intended to be used as a wrapper for the ++// map value in ++// :ref:`VirtualHost.typed_per_filter_config`, ++// :ref:`Route.typed_per_filter_config`, ++// or :ref:`WeightedCluster.ClusterWeight.typed_per_filter_config` ++// to add additional flags to the filter. ++// [#not-implemented-hide:] ++type FilterConfig struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ // The filter config. ++ Config *any.Any `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` ++ // If true, the filter is optional, meaning that if the client does ++ // not support the specified filter, it may ignore the map entry rather ++ // than rejecting the config. ++ IsOptional bool `protobuf:"varint,2,opt,name=is_optional,json=isOptional,proto3" json:"is_optional,omitempty"` ++} ++ ++func (x *FilterConfig) Reset() { ++ *x = FilterConfig{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[21] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *FilterConfig) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*FilterConfig) ProtoMessage() {} ++ ++func (x *FilterConfig) ProtoReflect() protoreflect.Message { ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[21] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use FilterConfig.ProtoReflect.Descriptor instead. ++func (*FilterConfig) Descriptor() ([]byte, []int) { ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{21} ++} ++ ++func (x *FilterConfig) GetConfig() *any.Any { ++ if x != nil { ++ return x.Config ++ } ++ return nil ++} ++ ++func (x *FilterConfig) GetIsOptional() bool { ++ if x != nil { ++ return x.IsOptional ++ } ++ return false ++} ++ ++// [#next-free-field: 13] ++type WeightedCluster_ClusterWeight struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields ++ ++ // Only one of *name* and *cluster_header* may be specified. ++ // [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1}] ++ // Name of the upstream cluster. The cluster must exist in the ++ // :ref:`cluster manager configuration `. ++ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` ++ // Only one of *name* and *cluster_header* may be specified. ++ // [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1 }] ++ // Envoy will determine the cluster to route to by reading the value of the ++ // HTTP header named by cluster_header from the request headers. If the ++ // header is not found or the referenced cluster does not exist, Envoy will ++ // return a 404 response. + // + // .. attention:: + // +@@ -3557,7 +3841,7 @@ type WeightedCluster_ClusterWeight struct { + func (x *WeightedCluster_ClusterWeight) Reset() { + *x = WeightedCluster_ClusterWeight{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[22] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3570,7 +3854,7 @@ func (x *WeightedCluster_ClusterWeight) String() string { + func (*WeightedCluster_ClusterWeight) ProtoMessage() {} + + func (x *WeightedCluster_ClusterWeight) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[22] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3685,7 +3969,7 @@ type RouteMatch_GrpcRouteMatchOptions struct { + func (x *RouteMatch_GrpcRouteMatchOptions) Reset() { + *x = RouteMatch_GrpcRouteMatchOptions{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[24] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3698,7 +3982,7 @@ func (x *RouteMatch_GrpcRouteMatchOptions) String() string { + func (*RouteMatch_GrpcRouteMatchOptions) ProtoMessage() {} + + func (x *RouteMatch_GrpcRouteMatchOptions) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[24] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3711,7 +3995,7 @@ func (x *RouteMatch_GrpcRouteMatchOptions) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteMatch_GrpcRouteMatchOptions.ProtoReflect.Descriptor instead. + func (*RouteMatch_GrpcRouteMatchOptions) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{4, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{5, 0} + } + + type RouteMatch_TlsContextMatchOptions struct { +@@ -3730,7 +4014,7 @@ type RouteMatch_TlsContextMatchOptions struct { + func (x *RouteMatch_TlsContextMatchOptions) Reset() { + *x = RouteMatch_TlsContextMatchOptions{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[25] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3743,7 +4027,7 @@ func (x *RouteMatch_TlsContextMatchOptions) String() string { + func (*RouteMatch_TlsContextMatchOptions) ProtoMessage() {} + + func (x *RouteMatch_TlsContextMatchOptions) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[25] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3756,7 +4040,7 @@ func (x *RouteMatch_TlsContextMatchOptions) ProtoReflect() protoreflect.Message + + // Deprecated: Use RouteMatch_TlsContextMatchOptions.ProtoReflect.Descriptor instead. + func (*RouteMatch_TlsContextMatchOptions) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{4, 1} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{5, 1} + } + + func (x *RouteMatch_TlsContextMatchOptions) GetPresented() *wrappers.BoolValue { +@@ -3783,7 +4067,7 @@ type RouteMatch_ConnectMatcher struct { + func (x *RouteMatch_ConnectMatcher) Reset() { + *x = RouteMatch_ConnectMatcher{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[26] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3796,7 +4080,7 @@ func (x *RouteMatch_ConnectMatcher) String() string { + func (*RouteMatch_ConnectMatcher) ProtoMessage() {} + + func (x *RouteMatch_ConnectMatcher) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[26] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3809,7 +4093,7 @@ func (x *RouteMatch_ConnectMatcher) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteMatch_ConnectMatcher.ProtoReflect.Descriptor instead. + func (*RouteMatch_ConnectMatcher) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{4, 2} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{5, 2} + } + + // The router is capable of shadowing traffic from one cluster to another. The current +@@ -3847,7 +4131,7 @@ type RouteAction_RequestMirrorPolicy struct { + func (x *RouteAction_RequestMirrorPolicy) Reset() { + *x = RouteAction_RequestMirrorPolicy{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[27] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3860,7 +4144,7 @@ func (x *RouteAction_RequestMirrorPolicy) String() string { + func (*RouteAction_RequestMirrorPolicy) ProtoMessage() {} + + func (x *RouteAction_RequestMirrorPolicy) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[27] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3873,7 +4157,7 @@ func (x *RouteAction_RequestMirrorPolicy) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteAction_RequestMirrorPolicy.ProtoReflect.Descriptor instead. + func (*RouteAction_RequestMirrorPolicy) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 0} + } + + func (x *RouteAction_RequestMirrorPolicy) GetCluster() string { +@@ -3937,7 +4221,7 @@ type RouteAction_HashPolicy struct { + func (x *RouteAction_HashPolicy) Reset() { + *x = RouteAction_HashPolicy{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[28] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -3950,7 +4234,7 @@ func (x *RouteAction_HashPolicy) String() string { + func (*RouteAction_HashPolicy) ProtoMessage() {} + + func (x *RouteAction_HashPolicy) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[28] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -3963,7 +4247,7 @@ func (x *RouteAction_HashPolicy) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteAction_HashPolicy.ProtoReflect.Descriptor instead. + func (*RouteAction_HashPolicy) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 1} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1} + } + + func (m *RouteAction_HashPolicy) GetPolicySpecifier() isRouteAction_HashPolicy_PolicySpecifier { +@@ -4081,7 +4365,7 @@ type RouteAction_UpgradeConfig struct { + func (x *RouteAction_UpgradeConfig) Reset() { + *x = RouteAction_UpgradeConfig{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[29] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4094,7 +4378,7 @@ func (x *RouteAction_UpgradeConfig) String() string { + func (*RouteAction_UpgradeConfig) ProtoMessage() {} + + func (x *RouteAction_UpgradeConfig) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[29] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4107,7 +4391,7 @@ func (x *RouteAction_UpgradeConfig) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteAction_UpgradeConfig.ProtoReflect.Descriptor instead. + func (*RouteAction_UpgradeConfig) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 2} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 2} + } + + func (x *RouteAction_UpgradeConfig) GetUpgradeType() string { +@@ -4162,7 +4446,7 @@ type RouteAction_MaxStreamDuration struct { + func (x *RouteAction_MaxStreamDuration) Reset() { + *x = RouteAction_MaxStreamDuration{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[30] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4175,7 +4459,7 @@ func (x *RouteAction_MaxStreamDuration) String() string { + func (*RouteAction_MaxStreamDuration) ProtoMessage() {} + + func (x *RouteAction_MaxStreamDuration) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[30] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4188,7 +4472,7 @@ func (x *RouteAction_MaxStreamDuration) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteAction_MaxStreamDuration.ProtoReflect.Descriptor instead. + func (*RouteAction_MaxStreamDuration) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 3} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 3} + } + + func (x *RouteAction_MaxStreamDuration) GetMaxStreamDuration() *duration.Duration { +@@ -4228,7 +4512,7 @@ type RouteAction_HashPolicy_Header struct { + func (x *RouteAction_HashPolicy_Header) Reset() { + *x = RouteAction_HashPolicy_Header{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[31] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4241,7 +4525,7 @@ func (x *RouteAction_HashPolicy_Header) String() string { + func (*RouteAction_HashPolicy_Header) ProtoMessage() {} + + func (x *RouteAction_HashPolicy_Header) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[31] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4254,7 +4538,7 @@ func (x *RouteAction_HashPolicy_Header) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteAction_HashPolicy_Header.ProtoReflect.Descriptor instead. + func (*RouteAction_HashPolicy_Header) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 1, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1, 0} + } + + func (x *RouteAction_HashPolicy_Header) GetHeaderName() string { +@@ -4306,7 +4590,7 @@ type RouteAction_HashPolicy_Cookie struct { + func (x *RouteAction_HashPolicy_Cookie) Reset() { + *x = RouteAction_HashPolicy_Cookie{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[32] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4319,7 +4603,7 @@ func (x *RouteAction_HashPolicy_Cookie) String() string { + func (*RouteAction_HashPolicy_Cookie) ProtoMessage() {} + + func (x *RouteAction_HashPolicy_Cookie) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[32] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4332,7 +4616,7 @@ func (x *RouteAction_HashPolicy_Cookie) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RouteAction_HashPolicy_Cookie.ProtoReflect.Descriptor instead. + func (*RouteAction_HashPolicy_Cookie) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 1, 1} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1, 1} + } + + func (x *RouteAction_HashPolicy_Cookie) GetName() string { +@@ -4368,7 +4652,7 @@ type RouteAction_HashPolicy_ConnectionProperties struct { + func (x *RouteAction_HashPolicy_ConnectionProperties) Reset() { + *x = RouteAction_HashPolicy_ConnectionProperties{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[33] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4381,7 +4665,7 @@ func (x *RouteAction_HashPolicy_ConnectionProperties) String() string { + func (*RouteAction_HashPolicy_ConnectionProperties) ProtoMessage() {} + + func (x *RouteAction_HashPolicy_ConnectionProperties) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[33] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[35] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4394,7 +4678,7 @@ func (x *RouteAction_HashPolicy_ConnectionProperties) ProtoReflect() protoreflec + + // Deprecated: Use RouteAction_HashPolicy_ConnectionProperties.ProtoReflect.Descriptor instead. + func (*RouteAction_HashPolicy_ConnectionProperties) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 1, 2} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1, 2} + } + + func (x *RouteAction_HashPolicy_ConnectionProperties) GetSourceIp() bool { +@@ -4418,7 +4702,7 @@ type RouteAction_HashPolicy_QueryParameter struct { + func (x *RouteAction_HashPolicy_QueryParameter) Reset() { + *x = RouteAction_HashPolicy_QueryParameter{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[34] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4431,7 +4715,7 @@ func (x *RouteAction_HashPolicy_QueryParameter) String() string { + func (*RouteAction_HashPolicy_QueryParameter) ProtoMessage() {} + + func (x *RouteAction_HashPolicy_QueryParameter) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[34] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4444,7 +4728,7 @@ func (x *RouteAction_HashPolicy_QueryParameter) ProtoReflect() protoreflect.Mess + + // Deprecated: Use RouteAction_HashPolicy_QueryParameter.ProtoReflect.Descriptor instead. + func (*RouteAction_HashPolicy_QueryParameter) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 1, 3} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1, 3} + } + + func (x *RouteAction_HashPolicy_QueryParameter) GetName() string { +@@ -4468,7 +4752,7 @@ type RouteAction_HashPolicy_FilterState struct { + func (x *RouteAction_HashPolicy_FilterState) Reset() { + *x = RouteAction_HashPolicy_FilterState{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[35] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4481,7 +4765,7 @@ func (x *RouteAction_HashPolicy_FilterState) String() string { + func (*RouteAction_HashPolicy_FilterState) ProtoMessage() {} + + func (x *RouteAction_HashPolicy_FilterState) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[35] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4494,7 +4778,7 @@ func (x *RouteAction_HashPolicy_FilterState) ProtoReflect() protoreflect.Message + + // Deprecated: Use RouteAction_HashPolicy_FilterState.ProtoReflect.Descriptor instead. + func (*RouteAction_HashPolicy_FilterState) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 1, 4} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1, 4} + } + + func (x *RouteAction_HashPolicy_FilterState) GetKey() string { +@@ -4520,7 +4804,7 @@ type RouteAction_UpgradeConfig_ConnectConfig struct { + func (x *RouteAction_UpgradeConfig_ConnectConfig) Reset() { + *x = RouteAction_UpgradeConfig_ConnectConfig{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[36] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4533,7 +4817,7 @@ func (x *RouteAction_UpgradeConfig_ConnectConfig) String() string { + func (*RouteAction_UpgradeConfig_ConnectConfig) ProtoMessage() {} + + func (x *RouteAction_UpgradeConfig_ConnectConfig) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[36] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[38] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4546,7 +4830,7 @@ func (x *RouteAction_UpgradeConfig_ConnectConfig) ProtoReflect() protoreflect.Me + + // Deprecated: Use RouteAction_UpgradeConfig_ConnectConfig.ProtoReflect.Descriptor instead. + func (*RouteAction_UpgradeConfig_ConnectConfig) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{6, 2, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 2, 0} + } + + func (x *RouteAction_UpgradeConfig_ConnectConfig) GetProxyProtocolConfig() *v3.ProxyProtocolConfig { +@@ -4579,7 +4863,7 @@ type RetryPolicy_RetryPriority struct { + func (x *RetryPolicy_RetryPriority) Reset() { + *x = RetryPolicy_RetryPriority{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[37] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4592,7 +4876,7 @@ func (x *RetryPolicy_RetryPriority) String() string { + func (*RetryPolicy_RetryPriority) ProtoMessage() {} + + func (x *RetryPolicy_RetryPriority) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[37] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[39] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4605,7 +4889,7 @@ func (x *RetryPolicy_RetryPriority) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RetryPolicy_RetryPriority.ProtoReflect.Descriptor instead. + func (*RetryPolicy_RetryPriority) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8, 0} + } + + func (x *RetryPolicy_RetryPriority) GetName() string { +@@ -4655,7 +4939,7 @@ type RetryPolicy_RetryHostPredicate struct { + func (x *RetryPolicy_RetryHostPredicate) Reset() { + *x = RetryPolicy_RetryHostPredicate{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[38] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4668,7 +4952,7 @@ func (x *RetryPolicy_RetryHostPredicate) String() string { + func (*RetryPolicy_RetryHostPredicate) ProtoMessage() {} + + func (x *RetryPolicy_RetryHostPredicate) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[38] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4681,7 +4965,7 @@ func (x *RetryPolicy_RetryHostPredicate) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RetryPolicy_RetryHostPredicate.ProtoReflect.Descriptor instead. + func (*RetryPolicy_RetryHostPredicate) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 1} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8, 1} + } + + func (x *RetryPolicy_RetryHostPredicate) GetName() string { +@@ -4735,7 +5019,7 @@ type RetryPolicy_RetryBackOff struct { + func (x *RetryPolicy_RetryBackOff) Reset() { + *x = RetryPolicy_RetryBackOff{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[39] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4748,7 +5032,7 @@ func (x *RetryPolicy_RetryBackOff) String() string { + func (*RetryPolicy_RetryBackOff) ProtoMessage() {} + + func (x *RetryPolicy_RetryBackOff) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[39] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4761,7 +5045,7 @@ func (x *RetryPolicy_RetryBackOff) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RetryPolicy_RetryBackOff.ProtoReflect.Descriptor instead. + func (*RetryPolicy_RetryBackOff) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 2} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8, 2} + } + + func (x *RetryPolicy_RetryBackOff) GetBaseInterval() *duration.Duration { +@@ -4796,7 +5080,7 @@ type RetryPolicy_ResetHeader struct { + func (x *RetryPolicy_ResetHeader) Reset() { + *x = RetryPolicy_ResetHeader{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[40] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4809,7 +5093,7 @@ func (x *RetryPolicy_ResetHeader) String() string { + func (*RetryPolicy_ResetHeader) ProtoMessage() {} + + func (x *RetryPolicy_ResetHeader) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[40] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4822,7 +5106,7 @@ func (x *RetryPolicy_ResetHeader) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RetryPolicy_ResetHeader.ProtoReflect.Descriptor instead. + func (*RetryPolicy_ResetHeader) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 3} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8, 3} + } + + func (x *RetryPolicy_ResetHeader) GetName() string { +@@ -4901,7 +5185,7 @@ type RetryPolicy_RateLimitedRetryBackOff struct { + func (x *RetryPolicy_RateLimitedRetryBackOff) Reset() { + *x = RetryPolicy_RateLimitedRetryBackOff{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[41] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4914,7 +5198,7 @@ func (x *RetryPolicy_RateLimitedRetryBackOff) String() string { + func (*RetryPolicy_RateLimitedRetryBackOff) ProtoMessage() {} + + func (x *RetryPolicy_RateLimitedRetryBackOff) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[41] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[43] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4927,7 +5211,7 @@ func (x *RetryPolicy_RateLimitedRetryBackOff) ProtoReflect() protoreflect.Messag + + // Deprecated: Use RetryPolicy_RateLimitedRetryBackOff.ProtoReflect.Descriptor instead. + func (*RetryPolicy_RateLimitedRetryBackOff) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{7, 4} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{8, 4} + } + + func (x *RetryPolicy_RateLimitedRetryBackOff) GetResetHeaders() []*RetryPolicy_ResetHeader { +@@ -4966,7 +5250,7 @@ type RateLimit_Action struct { + func (x *RateLimit_Action) Reset() { + *x = RateLimit_Action{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[42] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -4979,7 +5263,7 @@ func (x *RateLimit_Action) String() string { + func (*RateLimit_Action) ProtoMessage() {} + + func (x *RateLimit_Action) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[42] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[44] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -4992,7 +5276,7 @@ func (x *RateLimit_Action) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Action.ProtoReflect.Descriptor instead. + func (*RateLimit_Action) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0} + } + + func (m *RateLimit_Action) GetActionSpecifier() isRateLimit_Action_ActionSpecifier { +@@ -5152,7 +5436,7 @@ type RateLimit_Override struct { + func (x *RateLimit_Override) Reset() { + *x = RateLimit_Override{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[43] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5165,7 +5449,7 @@ func (x *RateLimit_Override) String() string { + func (*RateLimit_Override) ProtoMessage() {} + + func (x *RateLimit_Override) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[43] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[45] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5178,7 +5462,7 @@ func (x *RateLimit_Override) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Override.ProtoReflect.Descriptor instead. + func (*RateLimit_Override) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 1} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 1} + } + + func (m *RateLimit_Override) GetOverrideSpecifier() isRateLimit_Override_OverrideSpecifier { +@@ -5222,7 +5506,7 @@ type RateLimit_Action_SourceCluster struct { + func (x *RateLimit_Action_SourceCluster) Reset() { + *x = RateLimit_Action_SourceCluster{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[44] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5235,7 +5519,7 @@ func (x *RateLimit_Action_SourceCluster) String() string { + func (*RateLimit_Action_SourceCluster) ProtoMessage() {} + + func (x *RateLimit_Action_SourceCluster) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[44] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[46] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5248,7 +5532,7 @@ func (x *RateLimit_Action_SourceCluster) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Action_SourceCluster.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_SourceCluster) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 0} + } + + // The following descriptor entry is appended to the descriptor: +@@ -5276,7 +5560,7 @@ type RateLimit_Action_DestinationCluster struct { + func (x *RateLimit_Action_DestinationCluster) Reset() { + *x = RateLimit_Action_DestinationCluster{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[45] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5289,7 +5573,7 @@ func (x *RateLimit_Action_DestinationCluster) String() string { + func (*RateLimit_Action_DestinationCluster) ProtoMessage() {} + + func (x *RateLimit_Action_DestinationCluster) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[45] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[47] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5302,7 +5586,7 @@ func (x *RateLimit_Action_DestinationCluster) ProtoReflect() protoreflect.Messag + + // Deprecated: Use RateLimit_Action_DestinationCluster.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_DestinationCluster) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 1} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 1} + } + + // The following descriptor entry is appended when a header contains a key that matches the +@@ -5331,7 +5615,7 @@ type RateLimit_Action_RequestHeaders struct { + func (x *RateLimit_Action_RequestHeaders) Reset() { + *x = RateLimit_Action_RequestHeaders{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[46] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5344,7 +5628,7 @@ func (x *RateLimit_Action_RequestHeaders) String() string { + func (*RateLimit_Action_RequestHeaders) ProtoMessage() {} + + func (x *RateLimit_Action_RequestHeaders) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[46] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[48] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5357,7 +5641,7 @@ func (x *RateLimit_Action_RequestHeaders) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Action_RequestHeaders.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_RequestHeaders) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 2} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 2} + } + + func (x *RateLimit_Action_RequestHeaders) GetHeaderName() string { +@@ -5396,7 +5680,7 @@ type RateLimit_Action_RemoteAddress struct { + func (x *RateLimit_Action_RemoteAddress) Reset() { + *x = RateLimit_Action_RemoteAddress{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[47] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5409,7 +5693,7 @@ func (x *RateLimit_Action_RemoteAddress) String() string { + func (*RateLimit_Action_RemoteAddress) ProtoMessage() {} + + func (x *RateLimit_Action_RemoteAddress) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[47] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[49] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5422,7 +5706,7 @@ func (x *RateLimit_Action_RemoteAddress) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Action_RemoteAddress.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_RemoteAddress) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 3} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 3} + } + + // The following descriptor entry is appended to the descriptor: +@@ -5445,7 +5729,7 @@ type RateLimit_Action_GenericKey struct { + func (x *RateLimit_Action_GenericKey) Reset() { + *x = RateLimit_Action_GenericKey{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[48] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5458,7 +5742,7 @@ func (x *RateLimit_Action_GenericKey) String() string { + func (*RateLimit_Action_GenericKey) ProtoMessage() {} + + func (x *RateLimit_Action_GenericKey) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[48] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[50] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5471,7 +5755,7 @@ func (x *RateLimit_Action_GenericKey) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Action_GenericKey.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_GenericKey) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 4} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 4} + } + + func (x *RateLimit_Action_GenericKey) GetDescriptorValue() string { +@@ -5516,7 +5800,7 @@ type RateLimit_Action_HeaderValueMatch struct { + func (x *RateLimit_Action_HeaderValueMatch) Reset() { + *x = RateLimit_Action_HeaderValueMatch{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[49] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5529,7 +5813,7 @@ func (x *RateLimit_Action_HeaderValueMatch) String() string { + func (*RateLimit_Action_HeaderValueMatch) ProtoMessage() {} + + func (x *RateLimit_Action_HeaderValueMatch) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[49] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[51] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5542,7 +5826,7 @@ func (x *RateLimit_Action_HeaderValueMatch) ProtoReflect() protoreflect.Message + + // Deprecated: Use RateLimit_Action_HeaderValueMatch.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_HeaderValueMatch) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 5} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 5} + } + + func (x *RateLimit_Action_HeaderValueMatch) GetDescriptorValue() string { +@@ -5593,7 +5877,7 @@ type RateLimit_Action_DynamicMetaData struct { + func (x *RateLimit_Action_DynamicMetaData) Reset() { + *x = RateLimit_Action_DynamicMetaData{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[50] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5606,7 +5890,7 @@ func (x *RateLimit_Action_DynamicMetaData) String() string { + func (*RateLimit_Action_DynamicMetaData) ProtoMessage() {} + + func (x *RateLimit_Action_DynamicMetaData) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[50] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[52] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5619,7 +5903,7 @@ func (x *RateLimit_Action_DynamicMetaData) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Action_DynamicMetaData.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_DynamicMetaData) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 6} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 6} + } + + func (x *RateLimit_Action_DynamicMetaData) GetDescriptorKey() string { +@@ -5668,7 +5952,7 @@ type RateLimit_Action_MetaData struct { + func (x *RateLimit_Action_MetaData) Reset() { + *x = RateLimit_Action_MetaData{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[51] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5681,7 +5965,7 @@ func (x *RateLimit_Action_MetaData) String() string { + func (*RateLimit_Action_MetaData) ProtoMessage() {} + + func (x *RateLimit_Action_MetaData) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[51] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[53] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5694,7 +5978,7 @@ func (x *RateLimit_Action_MetaData) ProtoReflect() protoreflect.Message { + + // Deprecated: Use RateLimit_Action_MetaData.ProtoReflect.Descriptor instead. + func (*RateLimit_Action_MetaData) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 0, 7} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 0, 7} + } + + func (x *RateLimit_Action_MetaData) GetDescriptorKey() string { +@@ -5741,7 +6025,7 @@ type RateLimit_Override_DynamicMetadata struct { + func (x *RateLimit_Override_DynamicMetadata) Reset() { + *x = RateLimit_Override_DynamicMetadata{} + if protoimpl.UnsafeEnabled { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[52] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +@@ -5754,7 +6038,7 @@ func (x *RateLimit_Override_DynamicMetadata) String() string { + func (*RateLimit_Override_DynamicMetadata) ProtoMessage() {} + + func (x *RateLimit_Override_DynamicMetadata) ProtoReflect() protoreflect.Message { +- mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[52] ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[54] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { +@@ -5767,7 +6051,7 @@ func (x *RateLimit_Override_DynamicMetadata) ProtoReflect() protoreflect.Message + + // Deprecated: Use RateLimit_Override_DynamicMetadata.ProtoReflect.Descriptor instead. + func (*RateLimit_Override_DynamicMetadata) Descriptor() ([]byte, []int) { +- return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{15, 1, 0} ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{16, 1, 0} + } + + func (x *RateLimit_Override_DynamicMetadata) GetMetadataKey() *v34.MetadataKey { +@@ -5777,29 +6061,198 @@ func (x *RateLimit_Override_DynamicMetadata) GetMetadataKey() *v34.MetadataKey { + return nil + } + +-var File_envoy_config_route_v3_route_components_proto protoreflect.FileDescriptor ++// [#next-free-field: 18] ++type InternalActiveRedirectPolicy_RedirectPolicy struct { ++ state protoimpl.MessageState ++ sizeCache protoimpl.SizeCache ++ unknownFields protoimpl.UnknownFields + +-var file_envoy_config_route_v3_route_components_proto_rawDesc = []byte{ +- 0x0a, 0x2c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x63, 0x6f, +- 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, +- 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, +- 0x74, 0x65, 0x2e, 0x76, 0x33, 0x1a, 0x1f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x62, 0x61, 0x73, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x65, 0x78, 0x74, +- 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, +- 0x76, 0x33, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, +- 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, +- 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x33, 0x2f, 0x6d, +- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x65, +- 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, +- 0x72, 0x2f, 0x76, 0x33, 0x2f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x1a, 0x22, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x61, 0x74, +- 0x63, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x33, 0x2f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x25, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, +- 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x76, 0x33, 0x2f, 0x6d, 0x65, 0x74, ++ // An internal redirect is not handled, unless the number of previous internal redirects that a ++ // downstream request has encountered is lower than this value. ++ // In the case where a downstream request is bounced among multiple routes by internal redirect, ++ // the first route that hits this threshold, or does not set :ref:`internal_redirect_policy ++ // ` ++ // will pass the redirect back to downstream. ++ // ++ // If not specified, at most one redirect will be followed. ++ MaxInternalRedirects *wrappers.UInt32Value `protobuf:"bytes,10,opt,name=max_internal_redirects,json=maxInternalRedirects,proto3" json:"max_internal_redirects,omitempty"` ++ // Defines what upstream response codes are allowed to trigger internal redirect. ++ // All response codes support redirection except 200. ++ RedirectResponseCodes []uint32 `protobuf:"varint,11,rep,packed,name=redirect_response_codes,json=redirectResponseCodes,proto3" json:"redirect_response_codes,omitempty"` ++ // The URI of the redirect. ++ // ++ // Types that are assignable to RedirectUrlRewriteSpecifier: ++ // *InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrl ++ // *InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteRegex ++ RedirectUrlRewriteSpecifier isInternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteSpecifier `protobuf_oneof:"redirect_url_rewrite_specifier"` ++ // Specifies a list of predicates that are queried when an upstream response is deemed ++ // to trigger an internal redirect by all other criteria. Any predicate in the list can reject ++ // the redirect, causing the response to be proxied to downstream. ++ Predicates []*v3.TypedExtensionConfig `protobuf:"bytes,14,rep,name=predicates,proto3" json:"predicates,omitempty"` ++ // Allow internal redirect to follow a target URI with a different scheme than the value of ++ // x-forwarded-proto. The default is false. ++ AllowCrossSchemeRedirect bool `protobuf:"varint,15,opt,name=allow_cross_scheme_redirect,json=allowCrossSchemeRedirect,proto3" json:"allow_cross_scheme_redirect,omitempty"` ++ // HTTP headers to add to a local reply. This allows the response mapper to append, to add ++ // or to override headers of any local reply before it is sent to a downstream client. ++ RequestHeadersToAdd []*v3.HeaderValueOption `protobuf:"bytes,16,rep,name=request_headers_to_add,json=requestHeadersToAdd,proto3" json:"request_headers_to_add,omitempty"` ++ // Indicates that during forwarding, the host header will be swapped with ++ // this value. ++ HostRewriteLiteral string `protobuf:"bytes,17,opt,name=host_rewrite_literal,json=hostRewriteLiteral,proto3" json:"host_rewrite_literal,omitempty"` ++ // If true, the host name in the downstream request is used for redirection. ++ ForcedUseOriginalHost bool `protobuf:"varint,20,opt,name=forced_use_original_host,json=forcedUseOriginalHost,proto3" json:"forced_use_original_host,omitempty"` ++ ForcedAddHeaderBeforeRouteMatcher bool `protobuf:"varint,22,opt,name=forced_add_header_before_route_matcher,json=forcedAddHeaderBeforeRouteMatcher,proto3" json:"forced_add_header_before_route_matcher,omitempty"` ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) Reset() { ++ *x = InternalActiveRedirectPolicy_RedirectPolicy{} ++ if protoimpl.UnsafeEnabled { ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[55] ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ ms.StoreMessageInfo(mi) ++ } ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) String() string { ++ return protoimpl.X.MessageStringOf(x) ++} ++ ++func (*InternalActiveRedirectPolicy_RedirectPolicy) ProtoMessage() {} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) ProtoReflect() protoreflect.Message { ++ mi := &file_envoy_config_route_v3_route_components_proto_msgTypes[55] ++ if protoimpl.UnsafeEnabled && x != nil { ++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ++ if ms.LoadMessageInfo() == nil { ++ ms.StoreMessageInfo(mi) ++ } ++ return ms ++ } ++ return mi.MessageOf(x) ++} ++ ++// Deprecated: Use InternalActiveRedirectPolicy_RedirectPolicy.ProtoReflect.Descriptor instead. ++func (*InternalActiveRedirectPolicy_RedirectPolicy) Descriptor() ([]byte, []int) { ++ return file_envoy_config_route_v3_route_components_proto_rawDescGZIP(), []int{20, 0} ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetMaxInternalRedirects() *wrappers.UInt32Value { ++ if x != nil { ++ return x.MaxInternalRedirects ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetRedirectResponseCodes() []uint32 { ++ if x != nil { ++ return x.RedirectResponseCodes ++ } ++ return nil ++} ++ ++func (m *InternalActiveRedirectPolicy_RedirectPolicy) GetRedirectUrlRewriteSpecifier() isInternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteSpecifier { ++ if m != nil { ++ return m.RedirectUrlRewriteSpecifier ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetRedirectUrl() string { ++ if x, ok := x.GetRedirectUrlRewriteSpecifier().(*InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrl); ok { ++ return x.RedirectUrl ++ } ++ return "" ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetRedirectUrlRewriteRegex() *v31.RegexMatchAndSubstitute { ++ if x, ok := x.GetRedirectUrlRewriteSpecifier().(*InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteRegex); ok { ++ return x.RedirectUrlRewriteRegex ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetPredicates() []*v3.TypedExtensionConfig { ++ if x != nil { ++ return x.Predicates ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetAllowCrossSchemeRedirect() bool { ++ if x != nil { ++ return x.AllowCrossSchemeRedirect ++ } ++ return false ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetRequestHeadersToAdd() []*v3.HeaderValueOption { ++ if x != nil { ++ return x.RequestHeadersToAdd ++ } ++ return nil ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetHostRewriteLiteral() string { ++ if x != nil { ++ return x.HostRewriteLiteral ++ } ++ return "" ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetForcedUseOriginalHost() bool { ++ if x != nil { ++ return x.ForcedUseOriginalHost ++ } ++ return false ++} ++ ++func (x *InternalActiveRedirectPolicy_RedirectPolicy) GetForcedAddHeaderBeforeRouteMatcher() bool { ++ if x != nil { ++ return x.ForcedAddHeaderBeforeRouteMatcher ++ } ++ return false ++} ++ ++type isInternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteSpecifier interface { ++ isInternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteSpecifier() ++} ++ ++type InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrl struct { ++ RedirectUrl string `protobuf:"bytes,12,opt,name=redirect_url,json=redirectUrl,proto3,oneof"` ++} ++ ++type InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteRegex struct { ++ RedirectUrlRewriteRegex *v31.RegexMatchAndSubstitute `protobuf:"bytes,13,opt,name=redirect_url_rewrite_regex,json=redirectUrlRewriteRegex,proto3,oneof"` ++} ++ ++func (*InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrl) isInternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteSpecifier() { ++} ++ ++func (*InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteRegex) isInternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteSpecifier() { ++} ++ ++var File_envoy_config_route_v3_route_components_proto protoreflect.FileDescriptor ++ ++var file_envoy_config_route_v3_route_components_proto_rawDesc = []byte{ ++ 0x0a, 0x2c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, ++ 0x6f, 0x75, 0x74, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x63, 0x6f, ++ 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x2e, 0x76, 0x33, 0x1a, 0x1f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x62, 0x61, 0x73, 0x65, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x65, 0x78, 0x74, ++ 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, ++ 0x76, 0x33, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, ++ 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, ++ 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x33, 0x2f, 0x6d, ++ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, ++ 0x72, 0x2f, 0x76, 0x33, 0x2f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x1a, 0x22, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x61, 0x74, ++ 0x63, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x33, 0x2f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x25, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, ++ 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x76, 0x33, 0x2f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x65, 0x6e, 0x76, + 0x6f, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2f, + 0x76, 0x33, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x74, 0x61, 0x67, 0x2e, 0x70, 0x72, +@@ -6019,7 +6472,7 @@ var file_envoy_config_route_v3_route_components_proto_rawDesc = []byte{ + 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x42, 0x0d, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x03, 0xf8, 0x42, 0x01, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x08, 0x10, + 0x09, 0x52, 0x11, 0x70, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x22, 0xa5, 0x0a, 0x0a, 0x0f, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, ++ 0x6e, 0x66, 0x69, 0x67, 0x22, 0xd5, 0x0b, 0x0a, 0x0f, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, + 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x6e, 0x76, + 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, +@@ -6033,7 +6486,18 @@ var file_envoy_config_route_v3_route_components_proto_rawDesc = []byte{ + 0x01, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2c, + 0x0a, 0x12, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x75, 0x6e, 0x74, +- 0x69, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x1a, 0x92, 0x08, 0x0a, ++ 0x69, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x38, 0x0a, 0x18, ++ 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, ++ 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, ++ 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, ++ 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x74, 0x0a, 0x1f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, ++ 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, ++ 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0b, 0x32, ++ 0x2d, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, ++ 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, ++ 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, 0x1c, ++ 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, ++ 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x1a, 0x92, 0x08, 0x0a, + 0x0d, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2d, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xf2, 0x98, + 0xfe, 0x8f, 0x05, 0x13, 0x12, 0x11, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, +@@ -6101,7 +6565,16 @@ var file_envoy_config_route_v3_route_components_proto_rawDesc = []byte{ + 0x70, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x3a, 0x29, 0x9a, 0xc5, 0x88, 0x1e, 0x24, 0x0a, 0x22, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x57, 0x65, 0x69, +- 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x9e, 0x09, 0x0a, ++ 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x8d, 0x01, 0x0a, ++ 0x16, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, ++ 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x52, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, ++ 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, ++ 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, ++ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, ++ 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x69, ++ 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, ++ 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x9e, 0x09, 0x0a, + 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18, 0x0a, 0x06, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, +@@ -6214,7 +6687,7 @@ var file_envoy_config_route_v3_route_components_proto_rawDesc = []byte{ + 0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x52, 0x0c, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x12, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x52, +- 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xb2, 0x27, 0x0a, 0x0b, 0x52, 0x6f, 0x75, ++ 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xa7, 0x29, 0x0a, 0x0b, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x36, 0x0a, +@@ -6230,826 +6703,950 @@ var file_envoy_config_route_v3_route_components_proto_rawDesc = []byte{ + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x16, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, +- 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x8e, 0x01, 0x0a, 0x1f, 0x63, 0x6c, 0x75, +- 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, +- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x14, 0x20, 0x01, +- 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, +- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, +- 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, +- 0x64, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x1b, 0x63, 0x6c, +- 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, +- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x6d, 0x65, 0x74, +- 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, +- 0x61, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x61, 0x74, 0x63, 0x68, +- 0x12, 0x32, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, +- 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, +- 0x01, 0x02, 0xc8, 0x01, 0x00, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x77, +- 0x72, 0x69, 0x74, 0x65, 0x12, 0x53, 0x0a, 0x0d, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x72, 0x65, +- 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, +- 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x41, 0x6e, +- 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x67, +- 0x65, 0x78, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x3f, 0x0a, 0x14, 0x68, 0x6f, 0x73, +- 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, +- 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, +- 0x02, 0xc8, 0x01, 0x00, 0x48, 0x01, 0x52, 0x12, 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, +- 0x69, 0x74, 0x65, 0x4c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x48, 0x0a, 0x11, 0x61, 0x75, +- 0x74, 0x6f, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, +- 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, +- 0x65, 0x48, 0x01, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, +- 0x72, 0x69, 0x74, 0x65, 0x12, 0x3d, 0x0a, 0x13, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, +- 0x72, 0x69, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x1d, 0x20, 0x01, 0x28, +- 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x48, 0x01, +- 0x52, 0x11, 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x48, 0x65, 0x61, +- 0x64, 0x65, 0x72, 0x12, 0x67, 0x0a, 0x17, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, +- 0x69, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x23, +- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, +- 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, +- 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, +- 0x74, 0x75, 0x74, 0x65, 0x48, 0x01, 0x52, 0x14, 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, +- 0x69, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x33, 0x0a, 0x07, +- 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, +- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, +- 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, +- 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, +- 0x6f, 0x6e, 0x52, 0x0b, 0x69, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, +- 0x45, 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, +- 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, +- 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, +- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4f, 0x0a, 0x19, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, +- 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, +- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, +- 0x16, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, 0x70, 0x65, +- 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x6e, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, +- 0x73, 0x74, 0x5f, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, +- 0x65, 0x73, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, +- 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, +- 0x75, 0x65, 0x73, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, +- 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x50, +- 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, +- 0x69, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x76, 0x0a, 0x1f, 0x69, 0x6e, 0x6c, 0x69, ++ 0x6e, 0x65, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, ++ 0x66, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x27, 0x20, 0x01, 0x28, ++ 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, ++ 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, ++ 0x48, 0x00, 0x52, 0x1c, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, ++ 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, ++ 0x12, 0x8e, 0x01, 0x0a, 0x1f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x74, ++ 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, ++ 0x63, 0x6f, 0x64, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, ++ 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, ++ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, ++ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, ++ 0x01, 0x02, 0x10, 0x01, 0x52, 0x1b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x74, ++ 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, ++ 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6d, 0x61, ++ 0x74, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, + 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, +- 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, +- 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, +- 0x72, 0x69, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, +- 0x69, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x0a, 0x72, 0x61, 0x74, +- 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x5c, 0x0a, 0x16, 0x69, 0x6e, 0x63, 0x6c, 0x75, +- 0x64, 0x65, 0x5f, 0x76, 0x68, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, +- 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, ++ 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, ++ 0x61, 0x74, 0x61, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x32, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x66, ++ 0x69, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, ++ 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, 0x52, 0x0d, 0x70, ++ 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x53, 0x0a, 0x0d, ++ 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x20, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, ++ 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, ++ 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, ++ 0x75, 0x74, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x67, 0x65, 0x78, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, ++ 0x65, 0x12, 0x3f, 0x0a, 0x14, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, ++ 0x65, 0x5f, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, ++ 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, 0x48, 0x01, 0x52, 0x12, ++ 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x74, 0x65, 0x72, ++ 0x61, 0x6c, 0x12, 0x48, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, ++ 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, ++ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, ++ 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x01, 0x52, 0x0f, 0x61, 0x75, 0x74, ++ 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x3d, 0x0a, 0x13, ++ 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, ++ 0x64, 0x65, 0x72, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, ++ 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x48, 0x01, 0x52, 0x11, 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, ++ 0x77, 0x72, 0x69, 0x74, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x67, 0x0a, 0x17, 0x68, ++ 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, ++ 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, ++ 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x41, ++ 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x48, 0x01, 0x52, 0x14, ++ 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, ++ 0x65, 0x67, 0x65, 0x78, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, ++ 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, ++ 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x69, 0x64, 0x6c, ++ 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, ++ 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, ++ 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x69, 0x64, 0x6c, 0x65, ++ 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x45, 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x72, 0x79, ++ 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, ++ 0x79, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4f, ++ 0x0a, 0x19, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x74, ++ 0x79, 0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x21, 0x20, 0x01, 0x28, ++ 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x16, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, ++ 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, 0x70, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, ++ 0x6e, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x69, 0x72, 0x72, 0x6f, ++ 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, ++ 0x32, 0x36, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, ++ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x69, 0x72, 0x72, ++ 0x6f, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, ++ 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, ++ 0x4b, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, ++ 0x0e, 0x32, 0x25, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, ++ 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, ++ 0x10, 0x01, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x0b, ++ 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, ++ 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, ++ 0x6d, 0x69, 0x74, 0x52, 0x0a, 0x72, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, ++ 0x5c, 0x0a, 0x16, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x76, 0x68, 0x5f, 0x72, 0x61, ++ 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, ++ 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, ++ 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0b, 0x18, 0x01, 0x92, ++ 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, ++ 0x65, 0x56, 0x68, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x4e, 0x0a, ++ 0x0b, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x0f, 0x20, 0x03, ++ 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, ++ 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, ++ 0x79, 0x52, 0x0a, 0x68, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x35, 0x0a, ++ 0x04, 0x63, 0x6f, 0x72, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, ++ 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6f, 0x72, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x04, ++ 0x63, 0x6f, 0x72, 0x73, 0x12, 0x50, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x72, 0x70, 0x63, ++ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, ++ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, ++ 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, ++ 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x47, 0x72, 0x70, 0x63, 0x54, ++ 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x56, 0x0a, 0x13, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x74, ++ 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x1c, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0b, ++ 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x52, 0x11, 0x67, 0x72, 0x70, ++ 0x63, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x59, ++ 0x0a, 0x0f, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x73, 0x18, 0x19, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, ++ 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x67, 0x72, ++ 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x75, 0x70, 0x67, 0x72, 0x61, ++ 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x67, 0x0a, 0x18, 0x69, 0x6e, 0x74, ++ 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x70, ++ 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, ++ 0x2e, 0x76, 0x33, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, ++ 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x16, 0x69, 0x6e, 0x74, 0x65, ++ 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, ++ 0x63, 0x79, 0x12, 0x80, 0x01, 0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, ++ 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, ++ 0x1a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, ++ 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, ++ 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, ++ 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x52, 0x16, 0x69, ++ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, ++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, ++ 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, ++ 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, +- 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x56, 0x68, 0x52, 0x61, 0x74, 0x65, 0x4c, +- 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x70, 0x6f, +- 0x6c, 0x69, 0x63, 0x79, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x6e, 0x76, ++ 0x52, 0x14, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, ++ 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0c, 0x68, 0x65, 0x64, 0x67, 0x65, 0x5f, ++ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, ++ 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x64, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, ++ 0x52, 0x0b, 0x68, 0x65, 0x64, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x64, 0x0a, ++ 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x64, 0x75, 0x72, 0x61, ++ 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x6e, 0x76, + 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, +- 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, +- 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x68, 0x61, 0x73, 0x68, 0x50, +- 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x35, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x73, 0x18, 0x11, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6f, 0x72, 0x73, +- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x73, 0x12, 0x50, 0x0a, 0x10, +- 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, +- 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, +- 0x6e, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x52, 0x0e, +- 0x6d, 0x61, 0x78, 0x47, 0x72, 0x70, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x56, +- 0x0a, 0x13, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6f, +- 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, +- 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, +- 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, +- 0x33, 0x2e, 0x30, 0x52, 0x11, 0x67, 0x72, 0x70, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, +- 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x59, 0x0a, 0x0f, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, +- 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x19, 0x20, 0x03, 0x28, 0x0b, 0x32, +- 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, +- 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x52, 0x0e, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x73, 0x12, 0x67, 0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, +- 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x22, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x49, 0x6e, 0x74, 0x65, +- 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, +- 0x63, 0x79, 0x52, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, +- 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x80, 0x01, 0x0a, 0x18, 0x69, +- 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, +- 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, ++ 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, ++ 0x61, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, ++ 0x52, 0x11, 0x6d, 0x61, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x75, 0x72, 0x61, 0x74, ++ 0x69, 0x6f, 0x6e, 0x12, 0x7b, 0x0a, 0x1f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, ++ 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, ++ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, + 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, +- 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, +- 0x6e, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, +- 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, +- 0x04, 0x03, 0x33, 0x2e, 0x30, 0x52, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, +- 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, +- 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, +- 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, ++ 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x63, ++ 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, ++ 0x63, 0x79, 0x52, 0x1c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x63, 0x74, 0x69, ++ 0x76, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, ++ 0x1a, 0xa2, 0x02, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x69, 0x72, 0x72, ++ 0x6f, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x21, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, ++ 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, ++ 0x10, 0x01, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x59, 0x0a, 0x10, 0x72, ++ 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, ++ 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x75, 0x6e, ++ 0x74, 0x69, 0x6d, 0x65, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x50, 0x65, ++ 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x46, 0x72, ++ 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, ++ 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0b, 0x18, 0x01, 0x92, +- 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, +- 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x45, +- 0x0a, 0x0c, 0x68, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x1b, +- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x64, +- 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x68, 0x65, 0x64, 0x67, 0x65, 0x50, +- 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x64, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x74, 0x72, +- 0x65, 0x61, 0x6d, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x24, 0x20, 0x01, +- 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, +- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, +- 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x6d, 0x61, 0x78, 0x53, 0x74, 0x72, +- 0x65, 0x61, 0x6d, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xa2, 0x02, 0x0a, 0x13, +- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x50, 0x6f, 0x6c, +- 0x69, 0x63, 0x79, 0x12, 0x21, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, +- 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x63, +- 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x59, 0x0a, 0x10, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, +- 0x65, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, +- 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x46, +- 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, +- 0x52, 0x0f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, +- 0x6e, 0x12, 0x3f, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, +- 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, +- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, +- 0x65, 0x64, 0x3a, 0x39, 0x9a, 0xc5, 0x88, 0x1e, 0x34, 0x0a, 0x32, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, +- 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, +- 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x04, 0x08, +- 0x02, 0x10, 0x03, 0x52, 0x0b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, +- 0x1a, 0x96, 0x0a, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, +- 0x4e, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, +- 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, +- 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x48, +- 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, +- 0x4e, 0x0a, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, +- 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, +- 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, +- 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, +- 0x79, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, +- 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, +- 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, +- 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, +- 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, +- 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, +- 0x65, 0x73, 0x48, 0x00, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, +- 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x67, 0x0a, 0x0f, 0x71, 0x75, +- 0x65, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, ++ 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65, ++ 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x64, 0x3a, 0x39, 0x9a, 0xc5, 0x88, 0x1e, 0x34, 0x0a, 0x32, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, ++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x50, 0x6f, 0x6c, 0x69, ++ 0x63, 0x79, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x0b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, ++ 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x1a, 0x96, 0x0a, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, ++ 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4e, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, ++ 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, ++ 0x69, 0x63, 0x79, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, ++ 0x61, 0x64, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x02, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, ++ 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, ++ 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, ++ 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x79, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, ++ 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, +- 0x63, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, +- 0x72, 0x48, 0x00, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, +- 0x74, 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x0c, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x74, +- 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, +- 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, +- 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x74, +- 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, +- 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x1a, +- 0xc6, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x0b, 0x68, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, +- 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x0a, +- 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x53, 0x0a, 0x0d, 0x72, 0x65, +- 0x67, 0x65, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, +- 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, +- 0x61, 0x74, 0x63, 0x68, 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, +- 0x65, 0x52, 0x0c, 0x72, 0x65, 0x67, 0x65, 0x78, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x3a, +- 0x37, 0x9a, 0xc5, 0x88, 0x1e, 0x32, 0x0a, 0x30, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, +- 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, +- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, +- 0x79, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x9f, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6f, +- 0x6b, 0x69, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, +- 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, +- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x12, 0x0a, +- 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, +- 0x68, 0x3a, 0x37, 0x9a, 0xc5, 0x88, 0x1e, 0x32, 0x0a, 0x30, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, +- 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, +- 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, +- 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x1a, 0x7a, 0x0a, 0x14, 0x43, 0x6f, +- 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, +- 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, +- 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x70, 0x3a, +- 0x45, 0x9a, 0xc5, 0x88, 0x1e, 0x40, 0x0a, 0x3e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, +- 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, +- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, +- 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, +- 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x6e, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, +- 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, +- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, +- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x3f, 0x9a, 0xc5, 0x88, 0x1e, 0x3a, 0x0a, 0x38, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, ++ 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, ++ 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x48, 0x00, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x6e, 0x65, ++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, ++ 0x67, 0x0a, 0x0f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, ++ 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, ++ 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, + 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, + 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, +- 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x66, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, +- 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, +- 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x6b, 0x65, 0x79, +- 0x3a, 0x3c, 0x9a, 0xc5, 0x88, 0x1e, 0x37, 0x0a, 0x35, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, +- 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, +- 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, +- 0x63, 0x79, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3a, 0x30, +- 0x9a, 0xc5, 0x88, 0x1e, 0x2b, 0x0a, 0x29, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, +- 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, +- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, +- 0x42, 0x17, 0x0a, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, +- 0x66, 0x69, 0x65, 0x72, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x1a, 0xa3, 0x03, 0x0a, 0x0d, 0x55, 0x70, +- 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x0c, 0x75, +- 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, +- 0x52, 0x0b, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, +- 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, +- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, +- 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, +- 0x6c, 0x65, 0x64, 0x12, 0x65, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, +- 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, +- 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, +- 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6f, 0x6e, +- 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x8d, 0x01, 0x0a, 0x0d, 0x43, +- 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5d, 0x0a, 0x15, +- 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x76, 0x33, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, +- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, +- 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, +- 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, +- 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x6f, 0x73, 0x74, 0x3a, 0x33, 0x9a, 0xc5, 0x88, 0x1e, +- 0x2e, 0x0a, 0x2c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, +- 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, +- 0x6e, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, +- 0x88, 0x02, 0x0a, 0x11, 0x4d, 0x61, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x75, 0x72, +- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x74, 0x72, +- 0x65, 0x61, 0x6d, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, ++ 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x50, ++ 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x0c, 0x66, 0x69, 0x6c, 0x74, ++ 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, ++ 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x46, 0x69, ++ 0x6c, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x66, 0x69, 0x6c, ++ 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, ++ 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, ++ 0x69, 0x6e, 0x61, 0x6c, 0x1a, 0xc6, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, ++ 0x2e, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, ++ 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, 0x01, 0x01, ++ 0xc8, 0x01, 0x00, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, ++ 0x53, 0x0a, 0x0d, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, ++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, ++ 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, ++ 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, ++ 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x67, 0x65, 0x78, 0x52, 0x65, 0x77, ++ 0x72, 0x69, 0x74, 0x65, 0x3a, 0x37, 0x9a, 0xc5, 0x88, 0x1e, 0x32, 0x0a, 0x30, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, ++ 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, ++ 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x9f, 0x01, ++ 0x0a, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, ++ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, +- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x6d, +- 0x61, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, +- 0x12, 0x50, 0x0a, 0x17, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, +- 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x14, 0x67, 0x72, +- 0x70, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, +- 0x61, 0x78, 0x12, 0x56, 0x0a, 0x1a, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, +- 0x75, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, +- 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, ++ 0x74, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, ++ 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x3a, 0x37, 0x9a, 0xc5, 0x88, 0x1e, 0x32, 0x0a, 0x30, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, ++ 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, ++ 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x1a, ++ 0x7a, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, ++ 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, ++ 0x65, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, ++ 0x63, 0x65, 0x49, 0x70, 0x3a, 0x45, 0x9a, 0xc5, 0x88, 0x1e, 0x40, 0x0a, 0x3e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, ++ 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, ++ 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, ++ 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x6e, 0x0a, 0x0e, 0x51, ++ 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x1b, 0x0a, ++ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, ++ 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x3f, 0x9a, 0xc5, 0x88, 0x1e, ++ 0x3a, 0x0a, 0x38, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, ++ 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x51, 0x75, 0x65, ++ 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x66, 0x0a, 0x0b, 0x46, ++ 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x03, 0x6b, 0x65, ++ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, ++ 0x52, 0x03, 0x6b, 0x65, 0x79, 0x3a, 0x3c, 0x9a, 0xc5, 0x88, 0x1e, 0x37, 0x0a, 0x35, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, ++ 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, ++ 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x74, ++ 0x61, 0x74, 0x65, 0x3a, 0x30, 0x9a, 0xc5, 0x88, 0x1e, 0x2b, 0x0a, 0x29, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, ++ 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, ++ 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x17, 0x0a, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, ++ 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x1a, 0xa3, ++ 0x03, 0x0a, 0x0d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x12, 0x30, 0x0a, 0x0c, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, ++ 0x01, 0x02, 0xc8, 0x01, 0x00, 0x52, 0x0b, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x54, 0x79, ++ 0x70, 0x65, 0x12, 0x34, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, ++ 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x65, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, ++ 0x65, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x3e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, ++ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, ++ 0x8d, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x12, 0x5d, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x63, 0x6f, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x29, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, ++ 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x13, 0x70, 0x72, 0x6f, ++ 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x18, 0x02, ++ 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x6f, 0x73, 0x74, 0x3a, ++ 0x33, 0x9a, 0xc5, 0x88, 0x1e, 0x2e, 0x0a, 0x2c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, ++ 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, ++ 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x43, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x88, 0x02, 0x0a, 0x11, 0x4d, 0x61, 0x78, 0x53, 0x74, 0x72, 0x65, ++ 0x61, 0x6d, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x13, 0x6d, 0x61, ++ 0x78, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, ++ 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, ++ 0x6f, 0x6e, 0x52, 0x11, 0x6d, 0x61, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x75, 0x72, ++ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x17, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x74, 0x69, ++ 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x78, ++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, +- 0x6e, 0x52, 0x17, 0x67, 0x72, 0x70, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x45, 0x0a, 0x1b, 0x43, 0x6c, +- 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, +- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x45, 0x52, +- 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, +- 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, +- 0x01, 0x22, 0x5e, 0x0a, 0x16, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, +- 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x1e, 0x50, +- 0x41, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x52, 0x4f, 0x55, 0x47, 0x48, 0x5f, 0x49, 0x4e, 0x54, 0x45, +- 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x00, 0x12, +- 0x1c, 0x0a, 0x18, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, +- 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x1a, 0x02, 0x18, +- 0x01, 0x3a, 0x25, 0x9a, 0xc5, 0x88, 0x1e, 0x20, 0x0a, 0x1e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, +- 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, +- 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x18, 0x0a, 0x11, 0x63, 0x6c, 0x75, 0x73, +- 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x03, 0xf8, +- 0x42, 0x01, 0x42, 0x18, 0x0a, 0x16, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, +- 0x74, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x0c, +- 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x12, 0x10, 0x13, 0x4a, 0x04, 0x08, 0x13, 0x10, 0x14, 0x4a, 0x04, +- 0x08, 0x10, 0x10, 0x11, 0x4a, 0x04, 0x08, 0x16, 0x10, 0x17, 0x4a, 0x04, 0x08, 0x15, 0x10, 0x16, +- 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, +- 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0xbf, 0x10, +- 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x19, 0x0a, +- 0x08, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, +- 0x07, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x12, 0x52, 0x0a, 0x0b, 0x6e, 0x75, 0x6d, 0x5f, +- 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, +- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x13, 0xf2, 0x98, 0xfe, +- 0x8f, 0x05, 0x0d, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, +- 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0f, +- 0x70, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, +- 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, +- 0x52, 0x0d, 0x70, 0x65, 0x72, 0x54, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, +- 0x4a, 0x0a, 0x14, 0x70, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x6c, 0x65, 0x5f, +- 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, +- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x70, 0x65, 0x72, 0x54, 0x72, 0x79, +- 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x57, 0x0a, 0x0e, 0x72, +- 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, +- 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x72, 0x69, +- 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x72, 0x69, 0x6f, +- 0x72, 0x69, 0x74, 0x79, 0x12, 0x67, 0x0a, 0x14, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x68, 0x6f, +- 0x73, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x03, +- 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, +- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x48, 0x6f, 0x73, 0x74, +- 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x12, 0x72, 0x65, 0x74, 0x72, 0x79, +- 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, +- 0x18, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, +- 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, +- 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, +- 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, +- 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x16, 0x72, 0x65, 0x74, +- 0x72, 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, +- 0x74, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x21, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, +- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x5f, +- 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1d, +- 0x68, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x74, +- 0x72, 0x79, 0x4d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x12, 0x34, 0x0a, +- 0x16, 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, +- 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x14, 0x72, +- 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, +- 0x64, 0x65, 0x73, 0x12, 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x62, 0x61, 0x63, +- 0x6b, 0x5f, 0x6f, 0x66, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, +- 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, +- 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x52, 0x0c, 0x72, 0x65, +- 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x78, 0x0a, 0x1b, 0x72, 0x61, +- 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, +- 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x66, 0x66, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, +- 0x3a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, +- 0x69, 0x63, 0x79, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x52, +- 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x52, 0x17, 0x72, 0x61, 0x74, +- 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, +- 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x51, 0x0a, 0x11, 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, +- 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, ++ 0x6e, 0x52, 0x14, 0x67, 0x72, 0x70, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x65, ++ 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x78, 0x12, 0x56, 0x0a, 0x1a, 0x67, 0x72, 0x70, 0x63, 0x5f, ++ 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, ++ 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, ++ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, ++ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x17, 0x67, 0x72, 0x70, 0x63, 0x54, 0x69, 0x6d, 0x65, ++ 0x6f, 0x75, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, ++ 0x45, 0x0a, 0x1b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, ++ 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, ++ 0x0a, 0x13, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x41, 0x56, 0x41, 0x49, ++ 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, ++ 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x01, 0x22, 0x5e, 0x0a, 0x16, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, ++ 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, ++ 0x12, 0x22, 0x0a, 0x1e, 0x50, 0x41, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x52, 0x4f, 0x55, 0x47, 0x48, ++ 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, ++ 0x43, 0x54, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x5f, 0x49, ++ 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, ++ 0x10, 0x01, 0x1a, 0x02, 0x18, 0x01, 0x3a, 0x25, 0x9a, 0xc5, 0x88, 0x1e, 0x20, 0x0a, 0x1e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, ++ 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x18, 0x0a, ++ 0x11, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, ++ 0x65, 0x72, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x42, 0x18, 0x0a, 0x16, 0x68, 0x6f, 0x73, 0x74, 0x5f, ++ 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, ++ 0x72, 0x4a, 0x04, 0x08, 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x12, 0x10, 0x13, 0x4a, 0x04, 0x08, ++ 0x13, 0x10, 0x14, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x4a, 0x04, 0x08, 0x16, 0x10, 0x17, 0x4a, ++ 0x04, 0x08, 0x15, 0x10, 0x16, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x52, 0x15, 0x72, 0x65, 0x71, ++ 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, ++ 0x63, 0x79, 0x22, 0xbf, 0x10, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, ++ 0x63, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x6f, 0x6e, 0x18, 0x01, ++ 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x12, 0x52, 0x0a, ++ 0x0b, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, ++ 0x42, 0x13, 0xf2, 0x98, 0xfe, 0x8f, 0x05, 0x0d, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, ++ 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, ++ 0x73, 0x12, 0x41, 0x0a, 0x0f, 0x70, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, ++ 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, ++ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, ++ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x70, 0x65, 0x72, 0x54, 0x72, 0x79, 0x54, 0x69, 0x6d, ++ 0x65, 0x6f, 0x75, 0x74, 0x12, 0x4a, 0x0a, 0x14, 0x70, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x79, 0x5f, ++ 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0d, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x70, ++ 0x65, 0x72, 0x54, 0x72, 0x79, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, ++ 0x12, 0x57, 0x0a, 0x0e, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, ++ 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, ++ 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, ++ 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, ++ 0x72, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x72, 0x65, 0x74, 0x72, ++ 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x67, 0x0a, 0x14, 0x72, 0x65, 0x74, ++ 0x72, 0x79, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, ++ 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, ++ 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, ++ 0x79, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x12, ++ 0x72, 0x65, 0x74, 0x72, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, ++ 0x74, 0x65, 0x12, 0x64, 0x0a, 0x18, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x6f, 0x70, 0x74, 0x69, ++ 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x0c, ++ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, ++ 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x52, 0x16, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, ++ 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x21, 0x68, 0x6f, 0x73, 0x74, ++ 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, ++ 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x06, 0x20, ++ 0x01, 0x28, 0x03, 0x52, 0x1d, 0x68, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, ++ 0x6f, 0x6e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, ++ 0x74, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, ++ 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, ++ 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, ++ 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x74, 0x72, ++ 0x79, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x66, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x2f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, ++ 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, ++ 0x66, 0x52, 0x0c, 0x72, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, ++ 0x78, 0x0a, 0x1b, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x5f, ++ 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x66, 0x66, 0x18, 0x0b, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, ++ 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, ++ 0x69, 0x74, 0x65, 0x64, 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, ++ 0x52, 0x17, 0x72, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x52, 0x65, 0x74, ++ 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x51, 0x0a, 0x11, 0x72, 0x65, 0x74, ++ 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x09, ++ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, ++ 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x10, 0x72, 0x65, 0x74, 0x72, ++ 0x69, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x60, 0x0a, 0x19, ++ 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, ++ 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, +- 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x10, 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, +- 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x60, 0x0a, 0x19, 0x72, 0x65, 0x74, 0x72, 0x69, +- 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, +- 0x64, 0x65, 0x72, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, +- 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, +- 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, +- 0x52, 0x17, 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, +- 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0xb9, 0x01, 0x0a, 0x0d, 0x52, 0x65, +- 0x74, 0x72, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x04, 0x6e, +- 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, +- 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x74, 0x79, 0x70, 0x65, +- 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, +- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, +- 0x2e, 0x41, 0x6e, 0x79, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x64, 0x43, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x3a, 0x33, 0x9a, 0xc5, 0x88, 0x1e, 0x2e, 0x0a, 0x2c, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, +- 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, +- 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x0d, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x06, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xc3, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x48, +- 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, +- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, +- 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x74, 0x79, 0x70, +- 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, +- 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, +- 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x64, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x38, 0x9a, 0xc5, 0x88, 0x1e, 0x33, 0x0a, 0x31, 0x65, 0x6e, 0x76, +- 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, +- 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, +- 0x79, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x42, 0x0d, +- 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, +- 0x02, 0x10, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xd6, 0x01, 0x0a, 0x0c, +- 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x4a, 0x0a, 0x0d, +- 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, ++ 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x17, 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, ++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0xb9, ++ 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, ++ 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, ++ 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, ++ 0x0c, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x79, 0x70, ++ 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x33, 0x9a, 0xc5, 0x88, 0x1e, 0x2e, 0x0a, ++ 0x2c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, ++ 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x0d, 0x0a, ++ 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, 0x02, ++ 0x10, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xc3, 0x01, 0x0a, 0x12, 0x52, ++ 0x65, 0x74, 0x72, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, ++ 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, ++ 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, ++ 0x0a, 0x0c, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x79, ++ 0x70, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x38, 0x9a, 0xc5, 0x88, 0x1e, 0x33, ++ 0x0a, 0x31, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, ++ 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, ++ 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, ++ 0x61, 0x74, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x74, 0x79, ++ 0x70, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x1a, 0xd6, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, ++ 0x66, 0x12, 0x4a, 0x0a, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, ++ 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, ++ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, ++ 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0xaa, 0x01, 0x04, 0x08, 0x01, 0x2a, 0x00, 0x52, ++ 0x0c, 0x62, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x46, 0x0a, ++ 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, +- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, +- 0xfa, 0x42, 0x07, 0xaa, 0x01, 0x04, 0x08, 0x01, 0x2a, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x73, 0x65, +- 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x46, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, +- 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, +- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, +- 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0xaa, 0x01, +- 0x02, 0x2a, 0x00, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, +- 0x3a, 0x32, 0x9a, 0xc5, 0x88, 0x1e, 0x2d, 0x0a, 0x2b, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, +- 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, +- 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, +- 0x6b, 0x4f, 0x66, 0x66, 0x1a, 0x88, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x65, 0x74, 0x48, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, +- 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, 0x01, 0x01, 0xc8, 0x01, +- 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x56, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, +- 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, ++ 0xfa, 0x42, 0x05, 0xaa, 0x01, 0x02, 0x2a, 0x00, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, ++ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x3a, 0x32, 0x9a, 0xc5, 0x88, 0x1e, 0x2d, 0x0a, 0x2b, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, ++ 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x74, ++ 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x1a, 0x88, 0x01, 0x0a, 0x0b, 0x52, 0x65, ++ 0x73, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x04, 0x6e, 0x61, 0x6d, ++ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, ++ 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x56, 0x0a, 0x06, ++ 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, ++ 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, ++ 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, ++ 0x61, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, 0x66, 0x6f, ++ 0x72, 0x6d, 0x61, 0x74, 0x1a, 0xc0, 0x01, 0x0a, 0x17, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, ++ 0x69, 0x74, 0x65, 0x64, 0x52, 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, ++ 0x12, 0x5d, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, ++ 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, + 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, +- 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x08, 0xfa, +- 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x1a, +- 0xc0, 0x01, 0x0a, 0x17, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x52, +- 0x65, 0x74, 0x72, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x5d, 0x0a, 0x0d, 0x72, +- 0x65, 0x73, 0x65, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, +- 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, +- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, +- 0x65, 0x72, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x0c, 0x72, 0x65, +- 0x73, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x46, 0x0a, 0x0c, 0x6d, 0x61, +- 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, +- 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, +- 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, +- 0xaa, 0x01, 0x02, 0x2a, 0x00, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, +- 0x61, 0x6c, 0x22, 0x34, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, +- 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x43, 0x4f, 0x4e, +- 0x44, 0x53, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x49, 0x58, 0x5f, 0x54, 0x49, 0x4d, +- 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x10, 0x01, 0x3a, 0x25, 0x9a, 0xc5, 0x88, 0x1e, 0x20, 0x0a, +- 0x1e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, +- 0x75, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, +- 0x9c, 0x02, 0x0a, 0x0b, 0x48, 0x65, 0x64, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, +- 0x50, 0x0a, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, +- 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, +- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, +- 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x28, 0x01, +- 0x52, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, +- 0x73, 0x12, 0x5c, 0x0a, 0x19, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, +- 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, +- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, +- 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x50, +- 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x17, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, +- 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x12, +- 0x36, 0x0a, 0x18, 0x68, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x5f, +- 0x74, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, +- 0x08, 0x52, 0x14, 0x68, 0x65, 0x64, 0x67, 0x65, 0x4f, 0x6e, 0x50, 0x65, 0x72, 0x54, 0x72, 0x79, +- 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3a, 0x25, 0x9a, 0xc5, 0x88, 0x1e, 0x20, 0x0a, 0x1e, ++ 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, ++ 0x01, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, ++ 0x46, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, ++ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, ++ 0x42, 0x08, 0xfa, 0x42, 0x05, 0xaa, 0x01, 0x02, 0x2a, 0x00, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x49, ++ 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x34, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x65, 0x74, ++ 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x0b, 0x0a, 0x07, ++ 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x53, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x49, ++ 0x58, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x10, 0x01, 0x3a, 0x25, 0x9a, ++ 0xc5, 0x88, 0x1e, 0x20, 0x0a, 0x1e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, ++ 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, ++ 0x6c, 0x69, 0x63, 0x79, 0x22, 0x9c, 0x02, 0x0a, 0x0b, 0x48, 0x65, 0x64, 0x67, 0x65, 0x50, 0x6f, ++ 0x6c, 0x69, 0x63, 0x79, 0x12, 0x50, 0x0a, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, ++ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, ++ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, ++ 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0xfa, 0x42, ++ 0x04, 0x2a, 0x02, 0x28, 0x01, 0x52, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, ++ 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x5c, 0x0a, 0x19, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, ++ 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, ++ 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, ++ 0x6f, 0x6e, 0x61, 0x6c, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x17, 0x61, 0x64, 0x64, ++ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x68, ++ 0x61, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x18, 0x68, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x6f, 0x6e, ++ 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, ++ 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x68, 0x65, 0x64, 0x67, 0x65, 0x4f, 0x6e, 0x50, ++ 0x65, 0x72, 0x54, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3a, 0x25, 0x9a, 0xc5, ++ 0x88, 0x1e, 0x20, 0x0a, 0x1e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, ++ 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x64, 0x67, 0x65, 0x50, 0x6f, 0x6c, ++ 0x69, 0x63, 0x79, 0x22, 0xe1, 0x05, 0x0a, 0x0e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, ++ 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x73, 0x5f, ++ 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, ++ 0x52, 0x0d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, ++ 0x29, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, ++ 0x63, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, ++ 0x6d, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x30, 0x0a, 0x0d, 0x68, 0x6f, ++ 0x73, 0x74, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, ++ 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, 0x52, 0x0c, ++ 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x23, 0x0a, 0x0d, ++ 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x08, 0x20, ++ 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, ++ 0x74, 0x12, 0x32, 0x0a, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, ++ 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, ++ 0x01, 0x02, 0xc8, 0x01, 0x00, 0x48, 0x01, 0x52, 0x0c, 0x70, 0x61, 0x74, 0x68, 0x52, 0x65, 0x64, ++ 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x34, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, ++ 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, ++ 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, 0x48, 0x01, 0x52, 0x0d, 0x70, 0x72, ++ 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x55, 0x0a, 0x0d, 0x72, ++ 0x65, 0x67, 0x65, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, ++ 0x4d, 0x61, 0x74, 0x63, 0x68, 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, 0x75, ++ 0x74, 0x65, 0x48, 0x01, 0x52, 0x0c, 0x72, 0x65, 0x67, 0x65, 0x78, 0x52, 0x65, 0x77, 0x72, 0x69, ++ 0x74, 0x65, 0x12, 0x69, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, ++ 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, ++ 0x33, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, ++ 0x2e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, ++ 0x65, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, ++ 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, ++ 0x0b, 0x73, 0x74, 0x72, 0x69, 0x70, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, ++ 0x28, 0x08, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x69, 0x70, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x77, ++ 0x0a, 0x14, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, ++ 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x5f, ++ 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x09, 0x0a, ++ 0x05, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x45, 0x45, 0x5f, ++ 0x4f, 0x54, 0x48, 0x45, 0x52, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x45, 0x4d, 0x50, 0x4f, ++ 0x52, 0x41, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x03, 0x12, ++ 0x16, 0x0a, 0x12, 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x44, ++ 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x04, 0x3a, 0x28, 0x9a, 0xc5, 0x88, 0x1e, 0x23, 0x0a, 0x21, + 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, +- 0x74, 0x65, 0x2e, 0x48, 0x65, 0x64, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0xe1, +- 0x05, 0x0a, 0x0e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, +- 0x6e, 0x12, 0x27, 0x0a, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x73, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, +- 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0d, 0x68, 0x74, 0x74, +- 0x70, 0x73, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x0f, 0x73, 0x63, +- 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x07, 0x20, +- 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x52, 0x65, 0x64, +- 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x30, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, +- 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, +- 0x08, 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, 0x52, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x52, +- 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x5f, +- 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, +- 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x32, 0x0a, 0x0d, +- 0x70, 0x61, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, +- 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, +- 0x48, 0x01, 0x52, 0x0c, 0x70, 0x61, 0x74, 0x68, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, +- 0x12, 0x34, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, +- 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, +- 0x01, 0x02, 0xc8, 0x01, 0x00, 0x48, 0x01, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, +- 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x55, 0x0a, 0x0d, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, +- 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, +- 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, +- 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, +- 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x48, 0x01, 0x52, +- 0x0c, 0x72, 0x65, 0x67, 0x65, 0x78, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x69, 0x0a, +- 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, +- 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x64, +- 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x64, 0x69, +- 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, +- 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, +- 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x69, +- 0x70, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, +- 0x74, 0x72, 0x69, 0x70, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x77, 0x0a, 0x14, 0x52, 0x65, 0x64, +- 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, +- 0x65, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x41, +- 0x4e, 0x45, 0x4e, 0x54, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4f, 0x55, 0x4e, +- 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x45, 0x45, 0x5f, 0x4f, 0x54, 0x48, 0x45, 0x52, +- 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, +- 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x45, +- 0x52, 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, +- 0x10, 0x04, 0x3a, 0x28, 0x9a, 0xc5, 0x88, 0x1e, 0x23, 0x0a, 0x21, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x65, +- 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x1a, 0x0a, 0x18, +- 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, +- 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x42, 0x18, 0x0a, 0x16, 0x70, 0x61, 0x74, 0x68, +- 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, +- 0x65, 0x72, 0x22, 0xa0, 0x01, 0x0a, 0x14, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, +- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x06, 0x73, +- 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x0a, 0xfa, 0x42, 0x07, +- 0x2a, 0x05, 0x10, 0xd8, 0x04, 0x28, 0x64, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, +- 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, +- 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, +- 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, +- 0x04, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x2e, 0x9a, 0xc5, 0x88, 0x1e, 0x29, 0x0a, 0x27, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, +- 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x41, +- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x4e, 0x6f, 0x6e, 0x46, 0x6f, 0x72, 0x77, +- 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x91, 0x01, 0x0a, +- 0x09, 0x44, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x09, 0x6f, 0x70, +- 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, +- 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, +- 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74, 0x65, 0x18, 0x02, +- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, +- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, +- 0x52, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74, 0x65, 0x3a, 0x23, 0x9a, 0xc5, 0x88, +- 0x1e, 0x1e, 0x0a, 0x1c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, +- 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x44, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x6f, 0x72, +- 0x22, 0xd2, 0x02, 0x0a, 0x07, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x49, 0x0a, 0x0f, +- 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x18, +- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, ++ 0x74, 0x65, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, ++ 0x6e, 0x42, 0x1a, 0x0a, 0x18, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x77, 0x72, ++ 0x69, 0x74, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x42, 0x18, 0x0a, ++ 0x16, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x70, ++ 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0xa0, 0x01, 0x0a, 0x14, 0x44, 0x69, 0x72, 0x65, ++ 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, ++ 0x12, 0x22, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, ++ 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x2a, 0x05, 0x10, 0xd8, 0x04, 0x28, 0x64, 0x52, 0x06, 0x73, 0x74, ++ 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, ++ 0x75, 0x72, 0x63, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x2e, 0x9a, 0xc5, 0x88, 0x1e, ++ 0x29, 0x0a, 0x27, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, ++ 0x6f, 0x6e, 0x73, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x4e, 0x6f, ++ 0x6e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x74, 0x69, 0x6f, ++ 0x6e, 0x22, 0x91, 0x01, 0x0a, 0x09, 0x44, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, ++ 0x25, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, ++ 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x6f, 0x70, 0x65, ++ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, ++ 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, ++ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, ++ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74, 0x65, ++ 0x3a, 0x23, 0x9a, 0xc5, 0x88, 0x1e, 0x1e, 0x0a, 0x1c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, ++ 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x44, 0x65, 0x63, 0x6f, ++ 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 0xd2, 0x02, 0x0a, 0x07, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, ++ 0x67, 0x12, 0x49, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x61, 0x6d, 0x70, ++ 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x46, 0x72, 0x61, 0x63, 0x74, ++ 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x63, 0x6c, ++ 0x69, 0x65, 0x6e, 0x74, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x49, 0x0a, 0x0f, ++ 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x18, ++ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, +- 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, +- 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x49, 0x0a, 0x0f, 0x72, 0x61, 0x6e, 0x64, 0x6f, +- 0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, +- 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, +- 0x2e, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x50, 0x65, 0x72, 0x63, 0x65, +- 0x6e, 0x74, 0x52, 0x0e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, +- 0x6e, 0x67, 0x12, 0x4b, 0x0a, 0x10, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x61, +- 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, +- 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x46, 0x72, 0x61, +- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x0f, +- 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x12, +- 0x41, 0x0a, 0x0b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, +- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, +- 0x65, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x75, 0x73, +- 0x74, 0x6f, 0x6d, 0x54, 0x61, 0x67, 0x52, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x54, 0x61, +- 0x67, 0x73, 0x3a, 0x21, 0x9a, 0xc5, 0x88, 0x1e, 0x1c, 0x0a, 0x1a, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x54, 0x72, +- 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0xb4, 0x01, 0x0a, 0x0e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, +- 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, +- 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, +- 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, +- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, +- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x28, 0x9a, 0xc5, 0x88, 0x1e, 0x23, 0x0a, 0x21, 0x65, 0x6e, +- 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, +- 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, +- 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x07, 0x70, 0x61, 0x74, +- 0x74, 0x65, 0x72, 0x6e, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0xaa, 0x16, 0x0a, +- 0x09, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, +- 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, +- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, +- 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x18, 0x0a, +- 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x61, 0x62, +- 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x69, +- 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x4b, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, +- 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, +- 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x07, 0x61, 0x63, +- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, +- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, +- 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, +- 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x1a, 0x96, 0x12, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, +- 0x6e, 0x12, 0x5e, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x75, 0x73, +- 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x6e, 0x76, 0x6f, +- 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, +- 0x6f, 0x6e, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, +- 0x48, 0x00, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, +- 0x72, 0x12, 0x6d, 0x0a, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, +- 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, ++ 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x53, ++ 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x4b, 0x0a, 0x10, 0x6f, 0x76, 0x65, 0x72, 0x61, ++ 0x6c, 0x6c, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, ++ 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, ++ 0x33, 0x2e, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x50, 0x65, 0x72, 0x63, ++ 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x53, 0x61, 0x6d, 0x70, ++ 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x74, ++ 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x76, ++ 0x33, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x54, 0x61, 0x67, 0x52, 0x0a, 0x63, 0x75, 0x73, ++ 0x74, 0x6f, 0x6d, 0x54, 0x61, 0x67, 0x73, 0x3a, 0x21, 0x9a, 0xc5, 0x88, 0x1e, 0x1c, 0x0a, 0x1a, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0xb4, 0x01, 0x0a, 0x0e, 0x56, ++ 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, ++ 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, ++ 0x63, 0x68, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x0a, ++ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, ++ 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x28, 0x9a, 0xc5, 0x88, 0x1e, ++ 0x23, 0x0a, 0x21, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x6c, 0x75, ++ 0x73, 0x74, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, ++ 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, ++ 0x64, 0x22, 0xaa, 0x16, 0x0a, 0x09, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, ++ 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, ++ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, ++ 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0xfa, 0x42, ++ 0x04, 0x2a, 0x02, 0x18, 0x0a, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, ++ 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, ++ 0x09, 0x52, 0x0a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x4b, 0x0a, ++ 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, +- 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, +- 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x12, 0x64, 0x65, +- 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, +- 0x12, 0x61, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, +- 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, ++ 0x01, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x6c, 0x69, ++ 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x6e, 0x76, 0x6f, + 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, +- 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, +- 0x73, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, +- 0x65, 0x72, 0x73, 0x12, 0x5e, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x61, 0x64, +- 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x6e, ++ 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x4f, 0x76, 0x65, 0x72, ++ 0x72, 0x69, 0x64, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x1a, 0x96, 0x12, 0x0a, 0x06, ++ 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5e, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, ++ 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, ++ 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, ++ 0x75, 0x73, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, ++ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, ++ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, ++ 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x73, ++ 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x48, ++ 0x00, 0x52, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, ++ 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x61, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, ++ 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, ++ 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, ++ 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, ++ 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x5e, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, ++ 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, ++ 0x32, 0x35, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, ++ 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, ++ 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, ++ 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x0b, 0x67, 0x65, 0x6e, 0x65, ++ 0x72, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, ++ 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, ++ 0x79, 0x48, 0x00, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, ++ 0x68, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x65, 0x6e, + 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, +- 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, +- 0x73, 0x73, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, +- 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x6b, +- 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, +- 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, +- 0x6e, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, 0x0a, +- 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x68, 0x0a, 0x12, 0x68, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, +- 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, ++ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, ++ 0x4d, 0x61, 0x74, 0x63, 0x68, 0x48, 0x00, 0x52, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, ++ 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x77, 0x0a, 0x10, 0x64, 0x79, 0x6e, ++ 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, ++ 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, ++ 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x79, 0x6e, ++ 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x42, 0x11, 0x18, 0x01, ++ 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0xb8, 0xee, 0xf2, 0xd2, 0x05, 0x01, 0x48, ++ 0x00, 0x52, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, ++ 0x74, 0x61, 0x12, 0x4e, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, ++ 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, ++ 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, ++ 0x74, 0x61, 0x12, 0x4a, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, ++ 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, ++ 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x48, 0x00, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x49, ++ 0x0a, 0x0d, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, ++ 0x38, 0x9a, 0xc5, 0x88, 0x1e, 0x33, 0x0a, 0x31, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, ++ 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, ++ 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x6f, 0x75, 0x72, ++ 0x63, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x1a, 0x53, 0x0a, 0x12, 0x44, 0x65, 0x73, ++ 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, ++ 0x3d, 0x9a, 0xc5, 0x88, 0x1e, 0x38, 0x0a, 0x36, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, ++ 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, ++ 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x74, ++ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x1a, 0xd1, ++ 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, ++ 0x73, 0x12, 0x2e, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, ++ 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, ++ 0x65, 0x12, 0x2e, 0x0a, 0x0e, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, ++ 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, ++ 0x10, 0x01, 0x52, 0x0d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x4b, 0x65, ++ 0x79, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x69, 0x66, 0x5f, 0x61, 0x62, 0x73, ++ 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x49, ++ 0x66, 0x41, 0x62, 0x73, 0x65, 0x6e, 0x74, 0x3a, 0x39, 0x9a, 0xc5, 0x88, 0x1e, 0x34, 0x0a, 0x32, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, ++ 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, ++ 0x72, 0x73, 0x1a, 0x49, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, ++ 0x65, 0x73, 0x73, 0x3a, 0x38, 0x9a, 0xc5, 0x88, 0x1e, 0x33, 0x0a, 0x31, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, + 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, +- 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, +- 0x48, 0x00, 0x52, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, +- 0x61, 0x74, 0x63, 0x68, 0x12, 0x77, 0x0a, 0x10, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, +- 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, +- 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, +- 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, +- 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, +- 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x42, 0x11, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, +- 0x03, 0x33, 0x2e, 0x30, 0xb8, 0xee, 0xf2, 0xd2, 0x05, 0x01, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x79, +- 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4e, 0x0a, +- 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, +- 0x30, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, +- 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, +- 0x61, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4a, 0x0a, +- 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, +- 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, +- 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x09, +- 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x49, 0x0a, 0x0d, 0x53, 0x6f, 0x75, +- 0x72, 0x63, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x38, 0x9a, 0xc5, 0x88, 0x1e, +- 0x33, 0x0a, 0x31, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, +- 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, +- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x75, +- 0x73, 0x74, 0x65, 0x72, 0x1a, 0x53, 0x0a, 0x12, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, +- 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3d, 0x9a, 0xc5, 0x88, 0x1e, +- 0x38, 0x0a, 0x36, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, +- 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, +- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, +- 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x1a, 0xd1, 0x01, 0x0a, 0x0e, 0x52, 0x65, +- 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x0b, +- 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, +- 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x0e, +- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, +- 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x64, +- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x0e, +- 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x69, 0x66, 0x5f, 0x61, 0x62, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x03, +- 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x49, 0x66, 0x41, 0x62, 0x73, 0x65, +- 0x6e, 0x74, 0x3a, 0x39, 0x9a, 0xc5, 0x88, 0x1e, 0x34, 0x0a, 0x32, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, +- 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, +- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x49, 0x0a, +- 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x38, +- 0x9a, 0xc5, 0x88, 0x1e, 0x33, 0x0a, 0x31, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, +- 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, +- 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, +- 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x9e, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x6e, +- 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x63, 0x72, +- 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, +- 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, +- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, +- 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x4b, +- 0x65, 0x79, 0x3a, 0x35, 0x9a, 0xc5, 0x88, 0x1e, 0x30, 0x0a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, +- 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, +- 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x1a, 0x8c, 0x02, 0x0a, 0x10, 0x48, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x32, +- 0x0a, 0x10, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x61, 0x6c, +- 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, +- 0x01, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, +- 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x61, 0x74, +- 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, +- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x74, 0x63, +- 0x68, 0x12, 0x48, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, +- 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, +- 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, +- 0x08, 0x01, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x3b, 0x9a, 0xc5, 0x88, +- 0x1e, 0x36, 0x0a, 0x34, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, +- 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, +- 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, +- 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0xb8, 0x01, 0x0a, 0x0f, 0x44, 0x79, 0x6e, +- 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x0e, +- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, +- 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x64, +- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x0c, +- 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, ++ 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x9e, 0x01, ++ 0x0a, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x10, ++ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, ++ 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, ++ 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x6b, ++ 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, ++ 0x70, 0x74, 0x6f, 0x72, 0x4b, 0x65, 0x79, 0x3a, 0x35, 0x9a, 0xc5, 0x88, 0x1e, 0x30, 0x0a, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, ++ 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x1a, 0x8c, ++ 0x02, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, ++ 0x74, 0x63, 0x68, 0x12, 0x32, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, ++ 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, ++ 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, ++ 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, ++ 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, ++ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, ++ 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x65, 0x63, ++ 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x48, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, ++ 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, ++ 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x08, 0xfa, ++ 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, ++ 0x3a, 0x3b, 0x9a, 0xc5, 0x88, 0x1e, 0x36, 0x0a, 0x34, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, ++ 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, ++ 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, ++ 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0xb8, 0x01, ++ 0x0a, 0x0f, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, ++ 0x61, 0x12, 0x2e, 0x0a, 0x0e, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, ++ 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, ++ 0x10, 0x01, 0x52, 0x0d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x4b, 0x65, ++ 0x79, 0x12, 0x50, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, ++ 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, ++ 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x33, ++ 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x42, 0x08, 0xfa, 0x42, ++ 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, ++ 0x4b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, ++ 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, ++ 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xb4, 0x02, 0x0a, 0x08, 0x4d, 0x65, 0x74, ++ 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x0e, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, ++ 0x74, 0x6f, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, ++ 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, ++ 0x6f, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, ++ 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, ++ 0x61, 0x2e, 0x76, 0x33, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, ++ 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x61, ++ 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, ++ 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, ++ 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x59, 0x0a, 0x06, ++ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x65, ++ 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, ++ 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, ++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, ++ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, ++ 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x26, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, ++ 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0f, ++ 0x0a, 0x0b, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x10, 0x01, 0x3a, ++ 0x2a, 0x9a, 0xc5, 0x88, 0x1e, 0x25, 0x0a, 0x23, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, ++ 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, ++ 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x17, 0x0a, 0x10, 0x61, ++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, ++ 0x03, 0xf8, 0x42, 0x01, 0x1a, 0xf2, 0x01, 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, ++ 0x65, 0x12, 0x66, 0x0a, 0x10, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x65, 0x74, ++ 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, ++ 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x4f, 0x76, ++ 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, ++ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, ++ 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x63, 0x0a, 0x0f, 0x44, 0x79, 0x6e, ++ 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x0c, ++ 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x33, 0x2e, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, +- 0x01, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x12, 0x23, +- 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, +- 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, +- 0x6c, 0x75, 0x65, 0x1a, 0xb4, 0x02, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, +- 0x12, 0x2e, 0x0a, 0x0e, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x6b, +- 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, +- 0x01, 0x52, 0x0d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x4b, 0x65, 0x79, +- 0x12, 0x50, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, +- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, +- 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x33, 0x2e, +- 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, +- 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, +- 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, +- 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, +- 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x59, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, +- 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, +- 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, +- 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, +- 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, +- 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, +- 0x63, 0x65, 0x22, 0x26, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0b, 0x0a, 0x07, +- 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x4f, 0x55, +- 0x54, 0x45, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x10, 0x01, 0x3a, 0x2a, 0x9a, 0xc5, 0x88, 0x1e, +- 0x25, 0x0a, 0x23, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, +- 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, +- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x17, 0x0a, 0x10, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, +- 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x1a, +- 0xf2, 0x01, 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x66, 0x0a, 0x10, +- 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, +- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x52, +- 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, +- 0x65, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, +- 0x61, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, +- 0x64, 0x61, 0x74, 0x61, 0x1a, 0x63, 0x0a, 0x0f, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, +- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, +- 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, +- 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, +- 0x61, 0x74, 0x61, 0x2e, 0x76, 0x33, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, +- 0x65, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x6d, 0x65, +- 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x42, 0x19, 0x0a, 0x12, 0x6f, 0x76, 0x65, +- 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, +- 0x03, 0xf8, 0x42, 0x01, 0x3a, 0x23, 0x9a, 0xc5, 0x88, 0x1e, 0x1e, 0x0a, 0x1c, 0x65, 0x6e, 0x76, +- 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, +- 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0xa4, 0x05, 0x0a, 0x0d, 0x48, 0x65, +- 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x04, 0x6e, +- 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, +- 0x10, 0x01, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2e, +- 0x0a, 0x0b, 0x65, 0x78, 0x61, 0x63, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x04, 0x20, +- 0x01, 0x28, 0x09, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, +- 0x48, 0x00, 0x52, 0x0a, 0x65, 0x78, 0x61, 0x63, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x5c, +- 0x0a, 0x10, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x74, +- 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, +- 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, +- 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x0b, 0x18, +- 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x61, +- 0x66, 0x65, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3c, 0x0a, 0x0b, +- 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x76, +- 0x33, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0a, +- 0x72, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x25, 0x0a, 0x0d, 0x70, 0x72, +- 0x65, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, +- 0x08, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x74, 0x63, +- 0x68, 0x12, 0x37, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6d, 0x61, 0x74, 0x63, +- 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0x18, 0x01, 0xfa, 0x42, 0x04, 0x72, 0x02, +- 0x10, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x48, 0x00, 0x52, 0x0b, 0x70, +- 0x72, 0x65, 0x66, 0x69, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x37, 0x0a, 0x0c, 0x73, 0x75, +- 0x66, 0x66, 0x69, 0x78, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, +- 0x42, 0x12, 0x18, 0x01, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, +- 0x03, 0x33, 0x2e, 0x30, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x4d, 0x61, +- 0x74, 0x63, 0x68, 0x12, 0x3b, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x5f, +- 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0x18, 0x01, 0xfa, +- 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x48, +- 0x00, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, +- 0x12, 0x49, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, +- 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, +- 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x53, +- 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0b, +- 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x69, +- 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, +- 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x3a, 0x27, +- 0x9a, 0xc5, 0x88, 0x1e, 0x22, 0x0a, 0x20, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, +- 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, +- 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x18, 0x0a, 0x16, 0x68, 0x65, 0x61, 0x64, 0x65, +- 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, +- 0x72, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, +- 0x05, 0x10, 0x06, 0x52, 0x0b, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, +- 0x22, 0xa1, 0x02, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, +- 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x61, +- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x72, 0x05, 0x10, +- 0x01, 0x28, 0x80, 0x08, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x53, 0x0a, 0x0c, 0x73, 0x74, +- 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, +- 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, +- 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4d, +- 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, +- 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, ++ 0x01, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x42, 0x19, ++ 0x0a, 0x12, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, ++ 0x66, 0x69, 0x65, 0x72, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x3a, 0x23, 0x9a, 0xc5, 0x88, 0x1e, 0x1e, ++ 0x0a, 0x1c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, ++ 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0xa4, ++ 0x05, 0x0a, 0x0d, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, ++ 0x12, 0x21, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, ++ 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0xc0, 0x01, 0x01, 0xc8, 0x01, 0x00, 0x52, 0x04, 0x6e, ++ 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x0b, 0x65, 0x78, 0x61, 0x63, 0x74, 0x5f, 0x6d, 0x61, 0x74, ++ 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, ++ 0x04, 0x03, 0x33, 0x2e, 0x30, 0x48, 0x00, 0x52, 0x0a, 0x65, 0x78, 0x61, 0x63, 0x74, 0x4d, 0x61, ++ 0x74, 0x63, 0x68, 0x12, 0x5c, 0x0a, 0x10, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, ++ 0x78, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, ++ 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, ++ 0x65, 0x72, 0x42, 0x0b, 0x18, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x48, ++ 0x00, 0x52, 0x0e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, ++ 0x68, 0x12, 0x3c, 0x0a, 0x0b, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, ++ 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, ++ 0x79, 0x70, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x61, 0x6e, 0x67, ++ 0x65, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, + 0x25, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, +- 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, +- 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x3a, 0x2f, 0x9a, 0xc5, 0x88, 0x1e, 0x2a, 0x0a, 0x28, 0x65, +- 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, +- 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, +- 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x21, 0x0a, 0x1f, 0x71, 0x75, 0x65, 0x72, 0x79, +- 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, +- 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, +- 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x72, +- 0x65, 0x67, 0x65, 0x78, 0x22, 0xb9, 0x02, 0x0a, 0x16, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, +- 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, +- 0x52, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, +- 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, +- 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, +- 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x14, 0x6d, +- 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, +- 0x63, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x17, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, +- 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, +- 0x20, 0x03, 0x28, 0x0d, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x10, 0x05, 0x52, 0x15, +- 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, +- 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, +- 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, ++ 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x37, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, ++ 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0x18, 0x01, ++ 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, ++ 0x48, 0x00, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, ++ 0x37, 0x0a, 0x0c, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, ++ 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0x18, 0x01, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, ++ 0x92, 0xc7, 0x86, 0xd8, 0x04, 0x03, 0x33, 0x2e, 0x30, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x75, 0x66, ++ 0x66, 0x69, 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3b, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, ++ 0x61, 0x69, 0x6e, 0x73, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, ++ 0x42, 0x12, 0x18, 0x01, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x92, 0xc7, 0x86, 0xd8, 0x04, ++ 0x03, 0x33, 0x2e, 0x30, 0x48, 0x00, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, ++ 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x49, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, ++ 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, ++ 0x2e, 0x76, 0x33, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, ++ 0x72, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x74, 0x63, 0x68, ++ 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, ++ 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x4d, 0x61, ++ 0x74, 0x63, 0x68, 0x3a, 0x27, 0x9a, 0xc5, 0x88, 0x1e, 0x22, 0x0a, 0x20, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x48, ++ 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x18, 0x0a, 0x16, ++ 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x70, 0x65, ++ 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, ++ 0x10, 0x04, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x52, 0x0b, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0xa1, 0x02, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, ++ 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, ++ 0x1e, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xfa, ++ 0x42, 0x07, 0x72, 0x05, 0x10, 0x01, 0x28, 0x80, 0x08, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, ++ 0x53, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, ++ 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, ++ 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x53, 0x74, ++ 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x08, 0xfa, 0x42, 0x05, ++ 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4d, ++ 0x61, 0x74, 0x63, 0x68, 0x12, 0x25, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x5f, ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0c, 0x70, ++ 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x3a, 0x2f, 0x9a, 0xc5, 0x88, ++ 0x1e, 0x2a, 0x0a, 0x28, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, ++ 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, ++ 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x21, 0x0a, 0x1f, ++ 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4a, ++ 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, ++ 0x75, 0x65, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x22, 0xb9, 0x02, 0x0a, 0x16, 0x49, 0x6e, ++ 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, ++ 0x6c, 0x69, 0x63, 0x79, 0x12, 0x52, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, ++ 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, ++ 0x75, 0x65, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, ++ 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x17, 0x72, 0x65, 0x64, 0x69, ++ 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, ++ 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, ++ 0x02, 0x10, 0x05, 0x52, 0x15, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, ++ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x70, 0x72, ++ 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, ++ 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, ++ 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x64, ++ 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, ++ 0x63, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x64, ++ 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x6c, 0x6c, ++ 0x6f, 0x77, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x52, 0x65, 0x64, ++ 0x69, 0x72, 0x65, 0x63, 0x74, 0x22, 0xbe, 0x0d, 0x0a, 0x1c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, ++ 0x61, 0x6c, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, ++ 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x52, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, ++ 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, ++ 0x61, 0x6c, 0x75, 0x65, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, ++ 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x17, 0x72, 0x65, ++ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, ++ 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x42, 0x08, 0xfa, 0x42, 0x05, ++ 0x92, 0x01, 0x02, 0x10, 0x32, 0x52, 0x15, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, ++ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x0c, ++ 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x07, 0x20, 0x01, ++ 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x72, ++ 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x6d, 0x0a, 0x1a, 0x72, 0x65, ++ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, ++ 0x74, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, ++ 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x63, ++ 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4d, 0x61, 0x74, 0x63, ++ 0x68, 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x48, 0x00, ++ 0x52, 0x17, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x6c, 0x52, 0x65, 0x77, ++ 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x4a, 0x0a, 0x0a, 0x70, 0x72, 0x65, ++ 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, ++ 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, ++ 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x64, 0x69, ++ 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x63, ++ 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x64, 0x69, ++ 0x72, 0x65, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x6c, 0x6c, 0x6f, ++ 0x77, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x52, 0x65, 0x64, 0x69, ++ 0x72, 0x65, 0x63, 0x74, 0x12, 0x67, 0x0a, 0x16, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, ++ 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x64, 0x64, 0x18, 0x06, ++ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x48, 0x65, 0x61, 0x64, ++ 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0xfa, ++ 0x42, 0x06, 0x92, 0x01, 0x03, 0x10, 0xe8, 0x07, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, ++ 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x41, 0x64, 0x64, 0x12, 0x3d, 0x0a, ++ 0x14, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6c, 0x69, ++ 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, ++ 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, 0x52, 0x12, 0x68, 0x6f, 0x73, 0x74, 0x52, 0x65, ++ 0x77, 0x72, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x37, 0x0a, 0x18, ++ 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, ++ 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, ++ 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x55, 0x73, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, ++ 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x51, 0x0a, 0x26, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, ++ 0x61, 0x64, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, ++ 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, ++ 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x21, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x41, 0x64, 0x64, ++ 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x52, 0x6f, 0x75, 0x74, ++ 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, ++ 0x63, 0x69, 0x65, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x65, 0x6e, 0x76, ++ 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, ++ 0x76, 0x33, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x63, 0x74, 0x69, 0x76, ++ 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, ++ 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, ++ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0xa9, 0x06, 0x0a, 0x0e, 0x52, 0x65, 0x64, ++ 0x69, 0x72, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x52, 0x0a, 0x16, 0x6d, ++ 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, ++ 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, ++ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, ++ 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x49, 0x6e, ++ 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, ++ 0x40, 0x0a, 0x17, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, ++ 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0d, ++ 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x10, 0x32, 0x52, 0x15, 0x72, 0x65, 0x64, 0x69, ++ 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, ++ 0x73, 0x12, 0x2c, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, ++ 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, ++ 0x48, 0x00, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x6c, 0x12, ++ 0x6d, 0x0a, 0x1a, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x5f, ++ 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x0d, 0x20, ++ 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x74, 0x79, 0x70, 0x65, ++ 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x67, 0x65, ++ 0x78, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x41, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, ++ 0x75, 0x74, 0x65, 0x48, 0x00, 0x52, 0x17, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, ++ 0x72, 0x6c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x4a, ++ 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, ++ 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, ++ 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, ++ 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x61, 0x6c, ++ 0x6c, 0x6f, 0x77, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, ++ 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, ++ 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, 0x6d, ++ 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x67, 0x0a, 0x16, 0x72, 0x65, 0x71, ++ 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x74, 0x6f, 0x5f, ++ 0x61, 0x64, 0x64, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x76, 0x6f, + 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x33, +- 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, +- 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, +- 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, +- 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x43, 0x72, 0x6f, +- 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, +- 0x22, 0x5d, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, +- 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, +- 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, +- 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, +- 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, +- 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, +- 0x45, 0x0a, 0x23, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, +- 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, +- 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x42, 0x14, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6d, +- 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, +- 0xc8, 0xd1, 0x06, 0x02, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, ++ 0x6f, 0x6e, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x92, 0x01, 0x03, 0x10, 0xe8, 0x07, 0x52, 0x13, 0x72, ++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x54, 0x6f, 0x41, ++ 0x64, 0x64, 0x12, 0x3d, 0x0a, 0x14, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, ++ 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, ++ 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0xc0, 0x01, 0x02, 0xc8, 0x01, 0x00, 0x52, 0x12, 0x68, ++ 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x74, 0x65, 0x72, 0x61, ++ 0x6c, 0x12, 0x37, 0x0a, 0x18, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x5f, ++ 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x14, 0x20, ++ 0x01, 0x28, 0x08, 0x52, 0x15, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x55, 0x73, 0x65, 0x4f, 0x72, ++ 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x51, 0x0a, 0x26, 0x66, 0x6f, ++ 0x72, 0x63, 0x65, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, ++ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x74, ++ 0x63, 0x68, 0x65, 0x72, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x21, 0x66, 0x6f, 0x72, 0x63, ++ 0x65, 0x64, 0x41, 0x64, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x65, 0x66, 0x6f, 0x72, ++ 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x25, 0x0a, ++ 0x1e, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x72, 0x65, ++ 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, ++ 0x03, 0xf8, 0x42, 0x01, 0x42, 0x20, 0x0a, 0x1e, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, ++ 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x70, 0x65, ++ 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, ++ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x06, 0x63, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, ++ 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x70, 0x74, ++ 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x45, 0x0a, 0x23, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, ++ 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x33, 0x42, 0x14, 0x52, 0x6f, ++ 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, ++ 0x74, 0x6f, 0x50, 0x01, 0xba, 0x80, 0xc8, 0xd1, 0x06, 0x02, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +@@ -7065,7 +7662,7 @@ func file_envoy_config_route_v3_route_components_proto_rawDescGZIP() []byte { + } + + var file_envoy_config_route_v3_route_components_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +-var file_envoy_config_route_v3_route_components_proto_msgTypes = make([]protoimpl.MessageInfo, 53) ++var file_envoy_config_route_v3_route_components_proto_msgTypes = make([]protoimpl.MessageInfo, 56) + var file_envoy_config_route_v3_route_components_proto_goTypes = []interface{}{ + (VirtualHost_TlsRequirementType)(0), // 0: envoy.config.route.v3.VirtualHost.TlsRequirementType + (RouteAction_ClusterNotFoundResponseCode)(0), // 1: envoy.config.route.v3.RouteAction.ClusterNotFoundResponseCode +@@ -7077,225 +7674,241 @@ var file_envoy_config_route_v3_route_components_proto_goTypes = []interface{}{ + (*FilterAction)(nil), // 7: envoy.config.route.v3.FilterAction + (*Route)(nil), // 8: envoy.config.route.v3.Route + (*WeightedCluster)(nil), // 9: envoy.config.route.v3.WeightedCluster +- (*RouteMatch)(nil), // 10: envoy.config.route.v3.RouteMatch +- (*CorsPolicy)(nil), // 11: envoy.config.route.v3.CorsPolicy +- (*RouteAction)(nil), // 12: envoy.config.route.v3.RouteAction +- (*RetryPolicy)(nil), // 13: envoy.config.route.v3.RetryPolicy +- (*HedgePolicy)(nil), // 14: envoy.config.route.v3.HedgePolicy +- (*RedirectAction)(nil), // 15: envoy.config.route.v3.RedirectAction +- (*DirectResponseAction)(nil), // 16: envoy.config.route.v3.DirectResponseAction +- (*NonForwardingAction)(nil), // 17: envoy.config.route.v3.NonForwardingAction +- (*Decorator)(nil), // 18: envoy.config.route.v3.Decorator +- (*Tracing)(nil), // 19: envoy.config.route.v3.Tracing +- (*VirtualCluster)(nil), // 20: envoy.config.route.v3.VirtualCluster +- (*RateLimit)(nil), // 21: envoy.config.route.v3.RateLimit +- (*HeaderMatcher)(nil), // 22: envoy.config.route.v3.HeaderMatcher +- (*QueryParameterMatcher)(nil), // 23: envoy.config.route.v3.QueryParameterMatcher +- (*InternalRedirectPolicy)(nil), // 24: envoy.config.route.v3.InternalRedirectPolicy +- (*FilterConfig)(nil), // 25: envoy.config.route.v3.FilterConfig +- nil, // 26: envoy.config.route.v3.VirtualHost.TypedPerFilterConfigEntry +- nil, // 27: envoy.config.route.v3.Route.TypedPerFilterConfigEntry +- (*WeightedCluster_ClusterWeight)(nil), // 28: envoy.config.route.v3.WeightedCluster.ClusterWeight +- nil, // 29: envoy.config.route.v3.WeightedCluster.ClusterWeight.TypedPerFilterConfigEntry +- (*RouteMatch_GrpcRouteMatchOptions)(nil), // 30: envoy.config.route.v3.RouteMatch.GrpcRouteMatchOptions +- (*RouteMatch_TlsContextMatchOptions)(nil), // 31: envoy.config.route.v3.RouteMatch.TlsContextMatchOptions +- (*RouteMatch_ConnectMatcher)(nil), // 32: envoy.config.route.v3.RouteMatch.ConnectMatcher +- (*RouteAction_RequestMirrorPolicy)(nil), // 33: envoy.config.route.v3.RouteAction.RequestMirrorPolicy +- (*RouteAction_HashPolicy)(nil), // 34: envoy.config.route.v3.RouteAction.HashPolicy +- (*RouteAction_UpgradeConfig)(nil), // 35: envoy.config.route.v3.RouteAction.UpgradeConfig +- (*RouteAction_MaxStreamDuration)(nil), // 36: envoy.config.route.v3.RouteAction.MaxStreamDuration +- (*RouteAction_HashPolicy_Header)(nil), // 37: envoy.config.route.v3.RouteAction.HashPolicy.Header +- (*RouteAction_HashPolicy_Cookie)(nil), // 38: envoy.config.route.v3.RouteAction.HashPolicy.Cookie +- (*RouteAction_HashPolicy_ConnectionProperties)(nil), // 39: envoy.config.route.v3.RouteAction.HashPolicy.ConnectionProperties +- (*RouteAction_HashPolicy_QueryParameter)(nil), // 40: envoy.config.route.v3.RouteAction.HashPolicy.QueryParameter +- (*RouteAction_HashPolicy_FilterState)(nil), // 41: envoy.config.route.v3.RouteAction.HashPolicy.FilterState +- (*RouteAction_UpgradeConfig_ConnectConfig)(nil), // 42: envoy.config.route.v3.RouteAction.UpgradeConfig.ConnectConfig +- (*RetryPolicy_RetryPriority)(nil), // 43: envoy.config.route.v3.RetryPolicy.RetryPriority +- (*RetryPolicy_RetryHostPredicate)(nil), // 44: envoy.config.route.v3.RetryPolicy.RetryHostPredicate +- (*RetryPolicy_RetryBackOff)(nil), // 45: envoy.config.route.v3.RetryPolicy.RetryBackOff +- (*RetryPolicy_ResetHeader)(nil), // 46: envoy.config.route.v3.RetryPolicy.ResetHeader +- (*RetryPolicy_RateLimitedRetryBackOff)(nil), // 47: envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff +- (*RateLimit_Action)(nil), // 48: envoy.config.route.v3.RateLimit.Action +- (*RateLimit_Override)(nil), // 49: envoy.config.route.v3.RateLimit.Override +- (*RateLimit_Action_SourceCluster)(nil), // 50: envoy.config.route.v3.RateLimit.Action.SourceCluster +- (*RateLimit_Action_DestinationCluster)(nil), // 51: envoy.config.route.v3.RateLimit.Action.DestinationCluster +- (*RateLimit_Action_RequestHeaders)(nil), // 52: envoy.config.route.v3.RateLimit.Action.RequestHeaders +- (*RateLimit_Action_RemoteAddress)(nil), // 53: envoy.config.route.v3.RateLimit.Action.RemoteAddress +- (*RateLimit_Action_GenericKey)(nil), // 54: envoy.config.route.v3.RateLimit.Action.GenericKey +- (*RateLimit_Action_HeaderValueMatch)(nil), // 55: envoy.config.route.v3.RateLimit.Action.HeaderValueMatch +- (*RateLimit_Action_DynamicMetaData)(nil), // 56: envoy.config.route.v3.RateLimit.Action.DynamicMetaData +- (*RateLimit_Action_MetaData)(nil), // 57: envoy.config.route.v3.RateLimit.Action.MetaData +- (*RateLimit_Override_DynamicMetadata)(nil), // 58: envoy.config.route.v3.RateLimit.Override.DynamicMetadata +- (*v3.HeaderValueOption)(nil), // 59: envoy.config.core.v3.HeaderValueOption +- (*any.Any)(nil), // 60: google.protobuf.Any +- (*wrappers.UInt32Value)(nil), // 61: google.protobuf.UInt32Value +- (*v3.Metadata)(nil), // 62: envoy.config.core.v3.Metadata +- (*v31.RegexMatcher)(nil), // 63: envoy.type.matcher.v3.RegexMatcher +- (*wrappers.BoolValue)(nil), // 64: google.protobuf.BoolValue +- (*v3.RuntimeFractionalPercent)(nil), // 65: envoy.config.core.v3.RuntimeFractionalPercent +- (*v31.MetadataMatcher)(nil), // 66: envoy.type.matcher.v3.MetadataMatcher +- (*v31.StringMatcher)(nil), // 67: envoy.type.matcher.v3.StringMatcher +- (*v31.RegexMatchAndSubstitute)(nil), // 68: envoy.type.matcher.v3.RegexMatchAndSubstitute +- (*duration.Duration)(nil), // 69: google.protobuf.Duration +- (v3.RoutingPriority)(0), // 70: envoy.config.core.v3.RoutingPriority +- (*v3.TypedExtensionConfig)(nil), // 71: envoy.config.core.v3.TypedExtensionConfig +- (*v32.FractionalPercent)(nil), // 72: envoy.type.v3.FractionalPercent +- (*v3.DataSource)(nil), // 73: envoy.config.core.v3.DataSource +- (*v33.CustomTag)(nil), // 74: envoy.type.tracing.v3.CustomTag +- (*v32.Int64Range)(nil), // 75: envoy.type.v3.Int64Range +- (*v3.ProxyProtocolConfig)(nil), // 76: envoy.config.core.v3.ProxyProtocolConfig +- (*v34.MetadataKey)(nil), // 77: envoy.type.metadata.v3.MetadataKey ++ (*ClusterSpecifierPlugin)(nil), // 10: envoy.config.route.v3.ClusterSpecifierPlugin ++ (*RouteMatch)(nil), // 11: envoy.config.route.v3.RouteMatch ++ (*CorsPolicy)(nil), // 12: envoy.config.route.v3.CorsPolicy ++ (*RouteAction)(nil), // 13: envoy.config.route.v3.RouteAction ++ (*RetryPolicy)(nil), // 14: envoy.config.route.v3.RetryPolicy ++ (*HedgePolicy)(nil), // 15: envoy.config.route.v3.HedgePolicy ++ (*RedirectAction)(nil), // 16: envoy.config.route.v3.RedirectAction ++ (*DirectResponseAction)(nil), // 17: envoy.config.route.v3.DirectResponseAction ++ (*NonForwardingAction)(nil), // 18: envoy.config.route.v3.NonForwardingAction ++ (*Decorator)(nil), // 19: envoy.config.route.v3.Decorator ++ (*Tracing)(nil), // 20: envoy.config.route.v3.Tracing ++ (*VirtualCluster)(nil), // 21: envoy.config.route.v3.VirtualCluster ++ (*RateLimit)(nil), // 22: envoy.config.route.v3.RateLimit ++ (*HeaderMatcher)(nil), // 23: envoy.config.route.v3.HeaderMatcher ++ (*QueryParameterMatcher)(nil), // 24: envoy.config.route.v3.QueryParameterMatcher ++ (*InternalRedirectPolicy)(nil), // 25: envoy.config.route.v3.InternalRedirectPolicy ++ (*InternalActiveRedirectPolicy)(nil), // 26: envoy.config.route.v3.InternalActiveRedirectPolicy ++ (*FilterConfig)(nil), // 27: envoy.config.route.v3.FilterConfig ++ nil, // 28: envoy.config.route.v3.VirtualHost.TypedPerFilterConfigEntry ++ nil, // 29: envoy.config.route.v3.Route.TypedPerFilterConfigEntry ++ (*WeightedCluster_ClusterWeight)(nil), // 30: envoy.config.route.v3.WeightedCluster.ClusterWeight ++ nil, // 31: envoy.config.route.v3.WeightedCluster.ClusterWeight.TypedPerFilterConfigEntry ++ (*RouteMatch_GrpcRouteMatchOptions)(nil), // 32: envoy.config.route.v3.RouteMatch.GrpcRouteMatchOptions ++ (*RouteMatch_TlsContextMatchOptions)(nil), // 33: envoy.config.route.v3.RouteMatch.TlsContextMatchOptions ++ (*RouteMatch_ConnectMatcher)(nil), // 34: envoy.config.route.v3.RouteMatch.ConnectMatcher ++ (*RouteAction_RequestMirrorPolicy)(nil), // 35: envoy.config.route.v3.RouteAction.RequestMirrorPolicy ++ (*RouteAction_HashPolicy)(nil), // 36: envoy.config.route.v3.RouteAction.HashPolicy ++ (*RouteAction_UpgradeConfig)(nil), // 37: envoy.config.route.v3.RouteAction.UpgradeConfig ++ (*RouteAction_MaxStreamDuration)(nil), // 38: envoy.config.route.v3.RouteAction.MaxStreamDuration ++ (*RouteAction_HashPolicy_Header)(nil), // 39: envoy.config.route.v3.RouteAction.HashPolicy.Header ++ (*RouteAction_HashPolicy_Cookie)(nil), // 40: envoy.config.route.v3.RouteAction.HashPolicy.Cookie ++ (*RouteAction_HashPolicy_ConnectionProperties)(nil), // 41: envoy.config.route.v3.RouteAction.HashPolicy.ConnectionProperties ++ (*RouteAction_HashPolicy_QueryParameter)(nil), // 42: envoy.config.route.v3.RouteAction.HashPolicy.QueryParameter ++ (*RouteAction_HashPolicy_FilterState)(nil), // 43: envoy.config.route.v3.RouteAction.HashPolicy.FilterState ++ (*RouteAction_UpgradeConfig_ConnectConfig)(nil), // 44: envoy.config.route.v3.RouteAction.UpgradeConfig.ConnectConfig ++ (*RetryPolicy_RetryPriority)(nil), // 45: envoy.config.route.v3.RetryPolicy.RetryPriority ++ (*RetryPolicy_RetryHostPredicate)(nil), // 46: envoy.config.route.v3.RetryPolicy.RetryHostPredicate ++ (*RetryPolicy_RetryBackOff)(nil), // 47: envoy.config.route.v3.RetryPolicy.RetryBackOff ++ (*RetryPolicy_ResetHeader)(nil), // 48: envoy.config.route.v3.RetryPolicy.ResetHeader ++ (*RetryPolicy_RateLimitedRetryBackOff)(nil), // 49: envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff ++ (*RateLimit_Action)(nil), // 50: envoy.config.route.v3.RateLimit.Action ++ (*RateLimit_Override)(nil), // 51: envoy.config.route.v3.RateLimit.Override ++ (*RateLimit_Action_SourceCluster)(nil), // 52: envoy.config.route.v3.RateLimit.Action.SourceCluster ++ (*RateLimit_Action_DestinationCluster)(nil), // 53: envoy.config.route.v3.RateLimit.Action.DestinationCluster ++ (*RateLimit_Action_RequestHeaders)(nil), // 54: envoy.config.route.v3.RateLimit.Action.RequestHeaders ++ (*RateLimit_Action_RemoteAddress)(nil), // 55: envoy.config.route.v3.RateLimit.Action.RemoteAddress ++ (*RateLimit_Action_GenericKey)(nil), // 56: envoy.config.route.v3.RateLimit.Action.GenericKey ++ (*RateLimit_Action_HeaderValueMatch)(nil), // 57: envoy.config.route.v3.RateLimit.Action.HeaderValueMatch ++ (*RateLimit_Action_DynamicMetaData)(nil), // 58: envoy.config.route.v3.RateLimit.Action.DynamicMetaData ++ (*RateLimit_Action_MetaData)(nil), // 59: envoy.config.route.v3.RateLimit.Action.MetaData ++ (*RateLimit_Override_DynamicMetadata)(nil), // 60: envoy.config.route.v3.RateLimit.Override.DynamicMetadata ++ (*InternalActiveRedirectPolicy_RedirectPolicy)(nil), // 61: envoy.config.route.v3.InternalActiveRedirectPolicy.RedirectPolicy ++ (*v3.HeaderValueOption)(nil), // 62: envoy.config.core.v3.HeaderValueOption ++ (*any.Any)(nil), // 63: google.protobuf.Any ++ (*wrappers.UInt32Value)(nil), // 64: google.protobuf.UInt32Value ++ (*v3.Metadata)(nil), // 65: envoy.config.core.v3.Metadata ++ (*v3.TypedExtensionConfig)(nil), // 66: envoy.config.core.v3.TypedExtensionConfig ++ (*v31.RegexMatcher)(nil), // 67: envoy.type.matcher.v3.RegexMatcher ++ (*wrappers.BoolValue)(nil), // 68: google.protobuf.BoolValue ++ (*v3.RuntimeFractionalPercent)(nil), // 69: envoy.config.core.v3.RuntimeFractionalPercent ++ (*v31.MetadataMatcher)(nil), // 70: envoy.type.matcher.v3.MetadataMatcher ++ (*v31.StringMatcher)(nil), // 71: envoy.type.matcher.v3.StringMatcher ++ (*v31.RegexMatchAndSubstitute)(nil), // 72: envoy.type.matcher.v3.RegexMatchAndSubstitute ++ (*duration.Duration)(nil), // 73: google.protobuf.Duration ++ (v3.RoutingPriority)(0), // 74: envoy.config.core.v3.RoutingPriority ++ (*v32.FractionalPercent)(nil), // 75: envoy.type.v3.FractionalPercent ++ (*v3.DataSource)(nil), // 76: envoy.config.core.v3.DataSource ++ (*v33.CustomTag)(nil), // 77: envoy.type.tracing.v3.CustomTag ++ (*v32.Int64Range)(nil), // 78: envoy.type.v3.Int64Range ++ (*v3.ProxyProtocolConfig)(nil), // 79: envoy.config.core.v3.ProxyProtocolConfig ++ (*v34.MetadataKey)(nil), // 80: envoy.type.metadata.v3.MetadataKey + } + var file_envoy_config_route_v3_route_components_proto_depIdxs = []int32{ + 8, // 0: envoy.config.route.v3.VirtualHost.routes:type_name -> envoy.config.route.v3.Route + 0, // 1: envoy.config.route.v3.VirtualHost.require_tls:type_name -> envoy.config.route.v3.VirtualHost.TlsRequirementType +- 20, // 2: envoy.config.route.v3.VirtualHost.virtual_clusters:type_name -> envoy.config.route.v3.VirtualCluster +- 21, // 3: envoy.config.route.v3.VirtualHost.rate_limits:type_name -> envoy.config.route.v3.RateLimit +- 59, // 4: envoy.config.route.v3.VirtualHost.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 59, // 5: envoy.config.route.v3.VirtualHost.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 11, // 6: envoy.config.route.v3.VirtualHost.cors:type_name -> envoy.config.route.v3.CorsPolicy +- 26, // 7: envoy.config.route.v3.VirtualHost.typed_per_filter_config:type_name -> envoy.config.route.v3.VirtualHost.TypedPerFilterConfigEntry +- 13, // 8: envoy.config.route.v3.VirtualHost.retry_policy:type_name -> envoy.config.route.v3.RetryPolicy +- 60, // 9: envoy.config.route.v3.VirtualHost.retry_policy_typed_config:type_name -> google.protobuf.Any +- 14, // 10: envoy.config.route.v3.VirtualHost.hedge_policy:type_name -> envoy.config.route.v3.HedgePolicy +- 61, // 11: envoy.config.route.v3.VirtualHost.per_request_buffer_limit_bytes:type_name -> google.protobuf.UInt32Value +- 60, // 12: envoy.config.route.v3.FilterAction.action:type_name -> google.protobuf.Any +- 10, // 13: envoy.config.route.v3.Route.match:type_name -> envoy.config.route.v3.RouteMatch +- 12, // 14: envoy.config.route.v3.Route.route:type_name -> envoy.config.route.v3.RouteAction +- 15, // 15: envoy.config.route.v3.Route.redirect:type_name -> envoy.config.route.v3.RedirectAction +- 16, // 16: envoy.config.route.v3.Route.direct_response:type_name -> envoy.config.route.v3.DirectResponseAction ++ 21, // 2: envoy.config.route.v3.VirtualHost.virtual_clusters:type_name -> envoy.config.route.v3.VirtualCluster ++ 22, // 3: envoy.config.route.v3.VirtualHost.rate_limits:type_name -> envoy.config.route.v3.RateLimit ++ 62, // 4: envoy.config.route.v3.VirtualHost.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 62, // 5: envoy.config.route.v3.VirtualHost.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 12, // 6: envoy.config.route.v3.VirtualHost.cors:type_name -> envoy.config.route.v3.CorsPolicy ++ 28, // 7: envoy.config.route.v3.VirtualHost.typed_per_filter_config:type_name -> envoy.config.route.v3.VirtualHost.TypedPerFilterConfigEntry ++ 14, // 8: envoy.config.route.v3.VirtualHost.retry_policy:type_name -> envoy.config.route.v3.RetryPolicy ++ 63, // 9: envoy.config.route.v3.VirtualHost.retry_policy_typed_config:type_name -> google.protobuf.Any ++ 15, // 10: envoy.config.route.v3.VirtualHost.hedge_policy:type_name -> envoy.config.route.v3.HedgePolicy ++ 64, // 11: envoy.config.route.v3.VirtualHost.per_request_buffer_limit_bytes:type_name -> google.protobuf.UInt32Value ++ 63, // 12: envoy.config.route.v3.FilterAction.action:type_name -> google.protobuf.Any ++ 11, // 13: envoy.config.route.v3.Route.match:type_name -> envoy.config.route.v3.RouteMatch ++ 13, // 14: envoy.config.route.v3.Route.route:type_name -> envoy.config.route.v3.RouteAction ++ 16, // 15: envoy.config.route.v3.Route.redirect:type_name -> envoy.config.route.v3.RedirectAction ++ 17, // 16: envoy.config.route.v3.Route.direct_response:type_name -> envoy.config.route.v3.DirectResponseAction + 7, // 17: envoy.config.route.v3.Route.filter_action:type_name -> envoy.config.route.v3.FilterAction +- 17, // 18: envoy.config.route.v3.Route.non_forwarding_action:type_name -> envoy.config.route.v3.NonForwardingAction +- 62, // 19: envoy.config.route.v3.Route.metadata:type_name -> envoy.config.core.v3.Metadata +- 18, // 20: envoy.config.route.v3.Route.decorator:type_name -> envoy.config.route.v3.Decorator +- 27, // 21: envoy.config.route.v3.Route.typed_per_filter_config:type_name -> envoy.config.route.v3.Route.TypedPerFilterConfigEntry +- 59, // 22: envoy.config.route.v3.Route.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 59, // 23: envoy.config.route.v3.Route.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 19, // 24: envoy.config.route.v3.Route.tracing:type_name -> envoy.config.route.v3.Tracing +- 61, // 25: envoy.config.route.v3.Route.per_request_buffer_limit_bytes:type_name -> google.protobuf.UInt32Value +- 28, // 26: envoy.config.route.v3.WeightedCluster.clusters:type_name -> envoy.config.route.v3.WeightedCluster.ClusterWeight +- 61, // 27: envoy.config.route.v3.WeightedCluster.total_weight:type_name -> google.protobuf.UInt32Value +- 63, // 28: envoy.config.route.v3.RouteMatch.safe_regex:type_name -> envoy.type.matcher.v3.RegexMatcher +- 32, // 29: envoy.config.route.v3.RouteMatch.connect_matcher:type_name -> envoy.config.route.v3.RouteMatch.ConnectMatcher +- 64, // 30: envoy.config.route.v3.RouteMatch.case_sensitive:type_name -> google.protobuf.BoolValue +- 65, // 31: envoy.config.route.v3.RouteMatch.runtime_fraction:type_name -> envoy.config.core.v3.RuntimeFractionalPercent +- 22, // 32: envoy.config.route.v3.RouteMatch.headers:type_name -> envoy.config.route.v3.HeaderMatcher +- 23, // 33: envoy.config.route.v3.RouteMatch.query_parameters:type_name -> envoy.config.route.v3.QueryParameterMatcher +- 30, // 34: envoy.config.route.v3.RouteMatch.grpc:type_name -> envoy.config.route.v3.RouteMatch.GrpcRouteMatchOptions +- 31, // 35: envoy.config.route.v3.RouteMatch.tls_context:type_name -> envoy.config.route.v3.RouteMatch.TlsContextMatchOptions +- 66, // 36: envoy.config.route.v3.RouteMatch.dynamic_metadata:type_name -> envoy.type.matcher.v3.MetadataMatcher +- 67, // 37: envoy.config.route.v3.CorsPolicy.allow_origin_string_match:type_name -> envoy.type.matcher.v3.StringMatcher +- 64, // 38: envoy.config.route.v3.CorsPolicy.allow_credentials:type_name -> google.protobuf.BoolValue +- 65, // 39: envoy.config.route.v3.CorsPolicy.filter_enabled:type_name -> envoy.config.core.v3.RuntimeFractionalPercent +- 65, // 40: envoy.config.route.v3.CorsPolicy.shadow_enabled:type_name -> envoy.config.core.v3.RuntimeFractionalPercent +- 9, // 41: envoy.config.route.v3.RouteAction.weighted_clusters:type_name -> envoy.config.route.v3.WeightedCluster +- 1, // 42: envoy.config.route.v3.RouteAction.cluster_not_found_response_code:type_name -> envoy.config.route.v3.RouteAction.ClusterNotFoundResponseCode +- 62, // 43: envoy.config.route.v3.RouteAction.metadata_match:type_name -> envoy.config.core.v3.Metadata +- 68, // 44: envoy.config.route.v3.RouteAction.regex_rewrite:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute +- 64, // 45: envoy.config.route.v3.RouteAction.auto_host_rewrite:type_name -> google.protobuf.BoolValue +- 68, // 46: envoy.config.route.v3.RouteAction.host_rewrite_path_regex:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute +- 69, // 47: envoy.config.route.v3.RouteAction.timeout:type_name -> google.protobuf.Duration +- 69, // 48: envoy.config.route.v3.RouteAction.idle_timeout:type_name -> google.protobuf.Duration +- 13, // 49: envoy.config.route.v3.RouteAction.retry_policy:type_name -> envoy.config.route.v3.RetryPolicy +- 60, // 50: envoy.config.route.v3.RouteAction.retry_policy_typed_config:type_name -> google.protobuf.Any +- 33, // 51: envoy.config.route.v3.RouteAction.request_mirror_policies:type_name -> envoy.config.route.v3.RouteAction.RequestMirrorPolicy +- 70, // 52: envoy.config.route.v3.RouteAction.priority:type_name -> envoy.config.core.v3.RoutingPriority +- 21, // 53: envoy.config.route.v3.RouteAction.rate_limits:type_name -> envoy.config.route.v3.RateLimit +- 64, // 54: envoy.config.route.v3.RouteAction.include_vh_rate_limits:type_name -> google.protobuf.BoolValue +- 34, // 55: envoy.config.route.v3.RouteAction.hash_policy:type_name -> envoy.config.route.v3.RouteAction.HashPolicy +- 11, // 56: envoy.config.route.v3.RouteAction.cors:type_name -> envoy.config.route.v3.CorsPolicy +- 69, // 57: envoy.config.route.v3.RouteAction.max_grpc_timeout:type_name -> google.protobuf.Duration +- 69, // 58: envoy.config.route.v3.RouteAction.grpc_timeout_offset:type_name -> google.protobuf.Duration +- 35, // 59: envoy.config.route.v3.RouteAction.upgrade_configs:type_name -> envoy.config.route.v3.RouteAction.UpgradeConfig +- 24, // 60: envoy.config.route.v3.RouteAction.internal_redirect_policy:type_name -> envoy.config.route.v3.InternalRedirectPolicy +- 2, // 61: envoy.config.route.v3.RouteAction.internal_redirect_action:type_name -> envoy.config.route.v3.RouteAction.InternalRedirectAction +- 61, // 62: envoy.config.route.v3.RouteAction.max_internal_redirects:type_name -> google.protobuf.UInt32Value +- 14, // 63: envoy.config.route.v3.RouteAction.hedge_policy:type_name -> envoy.config.route.v3.HedgePolicy +- 36, // 64: envoy.config.route.v3.RouteAction.max_stream_duration:type_name -> envoy.config.route.v3.RouteAction.MaxStreamDuration +- 61, // 65: envoy.config.route.v3.RetryPolicy.num_retries:type_name -> google.protobuf.UInt32Value +- 69, // 66: envoy.config.route.v3.RetryPolicy.per_try_timeout:type_name -> google.protobuf.Duration +- 69, // 67: envoy.config.route.v3.RetryPolicy.per_try_idle_timeout:type_name -> google.protobuf.Duration +- 43, // 68: envoy.config.route.v3.RetryPolicy.retry_priority:type_name -> envoy.config.route.v3.RetryPolicy.RetryPriority +- 44, // 69: envoy.config.route.v3.RetryPolicy.retry_host_predicate:type_name -> envoy.config.route.v3.RetryPolicy.RetryHostPredicate +- 71, // 70: envoy.config.route.v3.RetryPolicy.retry_options_predicates:type_name -> envoy.config.core.v3.TypedExtensionConfig +- 45, // 71: envoy.config.route.v3.RetryPolicy.retry_back_off:type_name -> envoy.config.route.v3.RetryPolicy.RetryBackOff +- 47, // 72: envoy.config.route.v3.RetryPolicy.rate_limited_retry_back_off:type_name -> envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff +- 22, // 73: envoy.config.route.v3.RetryPolicy.retriable_headers:type_name -> envoy.config.route.v3.HeaderMatcher +- 22, // 74: envoy.config.route.v3.RetryPolicy.retriable_request_headers:type_name -> envoy.config.route.v3.HeaderMatcher +- 61, // 75: envoy.config.route.v3.HedgePolicy.initial_requests:type_name -> google.protobuf.UInt32Value +- 72, // 76: envoy.config.route.v3.HedgePolicy.additional_request_chance:type_name -> envoy.type.v3.FractionalPercent +- 68, // 77: envoy.config.route.v3.RedirectAction.regex_rewrite:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute +- 4, // 78: envoy.config.route.v3.RedirectAction.response_code:type_name -> envoy.config.route.v3.RedirectAction.RedirectResponseCode +- 73, // 79: envoy.config.route.v3.DirectResponseAction.body:type_name -> envoy.config.core.v3.DataSource +- 64, // 80: envoy.config.route.v3.Decorator.propagate:type_name -> google.protobuf.BoolValue +- 72, // 81: envoy.config.route.v3.Tracing.client_sampling:type_name -> envoy.type.v3.FractionalPercent +- 72, // 82: envoy.config.route.v3.Tracing.random_sampling:type_name -> envoy.type.v3.FractionalPercent +- 72, // 83: envoy.config.route.v3.Tracing.overall_sampling:type_name -> envoy.type.v3.FractionalPercent +- 74, // 84: envoy.config.route.v3.Tracing.custom_tags:type_name -> envoy.type.tracing.v3.CustomTag +- 22, // 85: envoy.config.route.v3.VirtualCluster.headers:type_name -> envoy.config.route.v3.HeaderMatcher +- 61, // 86: envoy.config.route.v3.RateLimit.stage:type_name -> google.protobuf.UInt32Value +- 48, // 87: envoy.config.route.v3.RateLimit.actions:type_name -> envoy.config.route.v3.RateLimit.Action +- 49, // 88: envoy.config.route.v3.RateLimit.limit:type_name -> envoy.config.route.v3.RateLimit.Override +- 63, // 89: envoy.config.route.v3.HeaderMatcher.safe_regex_match:type_name -> envoy.type.matcher.v3.RegexMatcher +- 75, // 90: envoy.config.route.v3.HeaderMatcher.range_match:type_name -> envoy.type.v3.Int64Range +- 67, // 91: envoy.config.route.v3.HeaderMatcher.string_match:type_name -> envoy.type.matcher.v3.StringMatcher +- 67, // 92: envoy.config.route.v3.QueryParameterMatcher.string_match:type_name -> envoy.type.matcher.v3.StringMatcher +- 61, // 93: envoy.config.route.v3.InternalRedirectPolicy.max_internal_redirects:type_name -> google.protobuf.UInt32Value +- 71, // 94: envoy.config.route.v3.InternalRedirectPolicy.predicates:type_name -> envoy.config.core.v3.TypedExtensionConfig +- 60, // 95: envoy.config.route.v3.FilterConfig.config:type_name -> google.protobuf.Any +- 60, // 96: envoy.config.route.v3.VirtualHost.TypedPerFilterConfigEntry.value:type_name -> google.protobuf.Any +- 60, // 97: envoy.config.route.v3.Route.TypedPerFilterConfigEntry.value:type_name -> google.protobuf.Any +- 61, // 98: envoy.config.route.v3.WeightedCluster.ClusterWeight.weight:type_name -> google.protobuf.UInt32Value +- 62, // 99: envoy.config.route.v3.WeightedCluster.ClusterWeight.metadata_match:type_name -> envoy.config.core.v3.Metadata +- 59, // 100: envoy.config.route.v3.WeightedCluster.ClusterWeight.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 59, // 101: envoy.config.route.v3.WeightedCluster.ClusterWeight.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption +- 29, // 102: envoy.config.route.v3.WeightedCluster.ClusterWeight.typed_per_filter_config:type_name -> envoy.config.route.v3.WeightedCluster.ClusterWeight.TypedPerFilterConfigEntry +- 60, // 103: envoy.config.route.v3.WeightedCluster.ClusterWeight.TypedPerFilterConfigEntry.value:type_name -> google.protobuf.Any +- 64, // 104: envoy.config.route.v3.RouteMatch.TlsContextMatchOptions.presented:type_name -> google.protobuf.BoolValue +- 64, // 105: envoy.config.route.v3.RouteMatch.TlsContextMatchOptions.validated:type_name -> google.protobuf.BoolValue +- 65, // 106: envoy.config.route.v3.RouteAction.RequestMirrorPolicy.runtime_fraction:type_name -> envoy.config.core.v3.RuntimeFractionalPercent +- 64, // 107: envoy.config.route.v3.RouteAction.RequestMirrorPolicy.trace_sampled:type_name -> google.protobuf.BoolValue +- 37, // 108: envoy.config.route.v3.RouteAction.HashPolicy.header:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.Header +- 38, // 109: envoy.config.route.v3.RouteAction.HashPolicy.cookie:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.Cookie +- 39, // 110: envoy.config.route.v3.RouteAction.HashPolicy.connection_properties:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.ConnectionProperties +- 40, // 111: envoy.config.route.v3.RouteAction.HashPolicy.query_parameter:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.QueryParameter +- 41, // 112: envoy.config.route.v3.RouteAction.HashPolicy.filter_state:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.FilterState +- 64, // 113: envoy.config.route.v3.RouteAction.UpgradeConfig.enabled:type_name -> google.protobuf.BoolValue +- 42, // 114: envoy.config.route.v3.RouteAction.UpgradeConfig.connect_config:type_name -> envoy.config.route.v3.RouteAction.UpgradeConfig.ConnectConfig +- 69, // 115: envoy.config.route.v3.RouteAction.MaxStreamDuration.max_stream_duration:type_name -> google.protobuf.Duration +- 69, // 116: envoy.config.route.v3.RouteAction.MaxStreamDuration.grpc_timeout_header_max:type_name -> google.protobuf.Duration +- 69, // 117: envoy.config.route.v3.RouteAction.MaxStreamDuration.grpc_timeout_header_offset:type_name -> google.protobuf.Duration +- 68, // 118: envoy.config.route.v3.RouteAction.HashPolicy.Header.regex_rewrite:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute +- 69, // 119: envoy.config.route.v3.RouteAction.HashPolicy.Cookie.ttl:type_name -> google.protobuf.Duration +- 76, // 120: envoy.config.route.v3.RouteAction.UpgradeConfig.ConnectConfig.proxy_protocol_config:type_name -> envoy.config.core.v3.ProxyProtocolConfig +- 60, // 121: envoy.config.route.v3.RetryPolicy.RetryPriority.typed_config:type_name -> google.protobuf.Any +- 60, // 122: envoy.config.route.v3.RetryPolicy.RetryHostPredicate.typed_config:type_name -> google.protobuf.Any +- 69, // 123: envoy.config.route.v3.RetryPolicy.RetryBackOff.base_interval:type_name -> google.protobuf.Duration +- 69, // 124: envoy.config.route.v3.RetryPolicy.RetryBackOff.max_interval:type_name -> google.protobuf.Duration +- 3, // 125: envoy.config.route.v3.RetryPolicy.ResetHeader.format:type_name -> envoy.config.route.v3.RetryPolicy.ResetHeaderFormat +- 46, // 126: envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff.reset_headers:type_name -> envoy.config.route.v3.RetryPolicy.ResetHeader +- 69, // 127: envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff.max_interval:type_name -> google.protobuf.Duration +- 50, // 128: envoy.config.route.v3.RateLimit.Action.source_cluster:type_name -> envoy.config.route.v3.RateLimit.Action.SourceCluster +- 51, // 129: envoy.config.route.v3.RateLimit.Action.destination_cluster:type_name -> envoy.config.route.v3.RateLimit.Action.DestinationCluster +- 52, // 130: envoy.config.route.v3.RateLimit.Action.request_headers:type_name -> envoy.config.route.v3.RateLimit.Action.RequestHeaders +- 53, // 131: envoy.config.route.v3.RateLimit.Action.remote_address:type_name -> envoy.config.route.v3.RateLimit.Action.RemoteAddress +- 54, // 132: envoy.config.route.v3.RateLimit.Action.generic_key:type_name -> envoy.config.route.v3.RateLimit.Action.GenericKey +- 55, // 133: envoy.config.route.v3.RateLimit.Action.header_value_match:type_name -> envoy.config.route.v3.RateLimit.Action.HeaderValueMatch +- 56, // 134: envoy.config.route.v3.RateLimit.Action.dynamic_metadata:type_name -> envoy.config.route.v3.RateLimit.Action.DynamicMetaData +- 57, // 135: envoy.config.route.v3.RateLimit.Action.metadata:type_name -> envoy.config.route.v3.RateLimit.Action.MetaData +- 71, // 136: envoy.config.route.v3.RateLimit.Action.extension:type_name -> envoy.config.core.v3.TypedExtensionConfig +- 58, // 137: envoy.config.route.v3.RateLimit.Override.dynamic_metadata:type_name -> envoy.config.route.v3.RateLimit.Override.DynamicMetadata +- 64, // 138: envoy.config.route.v3.RateLimit.Action.HeaderValueMatch.expect_match:type_name -> google.protobuf.BoolValue +- 22, // 139: envoy.config.route.v3.RateLimit.Action.HeaderValueMatch.headers:type_name -> envoy.config.route.v3.HeaderMatcher +- 77, // 140: envoy.config.route.v3.RateLimit.Action.DynamicMetaData.metadata_key:type_name -> envoy.type.metadata.v3.MetadataKey +- 77, // 141: envoy.config.route.v3.RateLimit.Action.MetaData.metadata_key:type_name -> envoy.type.metadata.v3.MetadataKey +- 5, // 142: envoy.config.route.v3.RateLimit.Action.MetaData.source:type_name -> envoy.config.route.v3.RateLimit.Action.MetaData.Source +- 77, // 143: envoy.config.route.v3.RateLimit.Override.DynamicMetadata.metadata_key:type_name -> envoy.type.metadata.v3.MetadataKey +- 144, // [144:144] is the sub-list for method output_type +- 144, // [144:144] is the sub-list for method input_type +- 144, // [144:144] is the sub-list for extension type_name +- 144, // [144:144] is the sub-list for extension extendee +- 0, // [0:144] is the sub-list for field type_name ++ 18, // 18: envoy.config.route.v3.Route.non_forwarding_action:type_name -> envoy.config.route.v3.NonForwardingAction ++ 65, // 19: envoy.config.route.v3.Route.metadata:type_name -> envoy.config.core.v3.Metadata ++ 19, // 20: envoy.config.route.v3.Route.decorator:type_name -> envoy.config.route.v3.Decorator ++ 29, // 21: envoy.config.route.v3.Route.typed_per_filter_config:type_name -> envoy.config.route.v3.Route.TypedPerFilterConfigEntry ++ 62, // 22: envoy.config.route.v3.Route.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 62, // 23: envoy.config.route.v3.Route.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 20, // 24: envoy.config.route.v3.Route.tracing:type_name -> envoy.config.route.v3.Tracing ++ 64, // 25: envoy.config.route.v3.Route.per_request_buffer_limit_bytes:type_name -> google.protobuf.UInt32Value ++ 30, // 26: envoy.config.route.v3.WeightedCluster.clusters:type_name -> envoy.config.route.v3.WeightedCluster.ClusterWeight ++ 64, // 27: envoy.config.route.v3.WeightedCluster.total_weight:type_name -> google.protobuf.UInt32Value ++ 10, // 28: envoy.config.route.v3.WeightedCluster.inline_cluster_specifier_plugin:type_name -> envoy.config.route.v3.ClusterSpecifierPlugin ++ 66, // 29: envoy.config.route.v3.ClusterSpecifierPlugin.extension:type_name -> envoy.config.core.v3.TypedExtensionConfig ++ 67, // 30: envoy.config.route.v3.RouteMatch.safe_regex:type_name -> envoy.type.matcher.v3.RegexMatcher ++ 34, // 31: envoy.config.route.v3.RouteMatch.connect_matcher:type_name -> envoy.config.route.v3.RouteMatch.ConnectMatcher ++ 68, // 32: envoy.config.route.v3.RouteMatch.case_sensitive:type_name -> google.protobuf.BoolValue ++ 69, // 33: envoy.config.route.v3.RouteMatch.runtime_fraction:type_name -> envoy.config.core.v3.RuntimeFractionalPercent ++ 23, // 34: envoy.config.route.v3.RouteMatch.headers:type_name -> envoy.config.route.v3.HeaderMatcher ++ 24, // 35: envoy.config.route.v3.RouteMatch.query_parameters:type_name -> envoy.config.route.v3.QueryParameterMatcher ++ 32, // 36: envoy.config.route.v3.RouteMatch.grpc:type_name -> envoy.config.route.v3.RouteMatch.GrpcRouteMatchOptions ++ 33, // 37: envoy.config.route.v3.RouteMatch.tls_context:type_name -> envoy.config.route.v3.RouteMatch.TlsContextMatchOptions ++ 70, // 38: envoy.config.route.v3.RouteMatch.dynamic_metadata:type_name -> envoy.type.matcher.v3.MetadataMatcher ++ 71, // 39: envoy.config.route.v3.CorsPolicy.allow_origin_string_match:type_name -> envoy.type.matcher.v3.StringMatcher ++ 68, // 40: envoy.config.route.v3.CorsPolicy.allow_credentials:type_name -> google.protobuf.BoolValue ++ 69, // 41: envoy.config.route.v3.CorsPolicy.filter_enabled:type_name -> envoy.config.core.v3.RuntimeFractionalPercent ++ 69, // 42: envoy.config.route.v3.CorsPolicy.shadow_enabled:type_name -> envoy.config.core.v3.RuntimeFractionalPercent ++ 9, // 43: envoy.config.route.v3.RouteAction.weighted_clusters:type_name -> envoy.config.route.v3.WeightedCluster ++ 10, // 44: envoy.config.route.v3.RouteAction.inline_cluster_specifier_plugin:type_name -> envoy.config.route.v3.ClusterSpecifierPlugin ++ 1, // 45: envoy.config.route.v3.RouteAction.cluster_not_found_response_code:type_name -> envoy.config.route.v3.RouteAction.ClusterNotFoundResponseCode ++ 65, // 46: envoy.config.route.v3.RouteAction.metadata_match:type_name -> envoy.config.core.v3.Metadata ++ 72, // 47: envoy.config.route.v3.RouteAction.regex_rewrite:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute ++ 68, // 48: envoy.config.route.v3.RouteAction.auto_host_rewrite:type_name -> google.protobuf.BoolValue ++ 72, // 49: envoy.config.route.v3.RouteAction.host_rewrite_path_regex:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute ++ 73, // 50: envoy.config.route.v3.RouteAction.timeout:type_name -> google.protobuf.Duration ++ 73, // 51: envoy.config.route.v3.RouteAction.idle_timeout:type_name -> google.protobuf.Duration ++ 14, // 52: envoy.config.route.v3.RouteAction.retry_policy:type_name -> envoy.config.route.v3.RetryPolicy ++ 63, // 53: envoy.config.route.v3.RouteAction.retry_policy_typed_config:type_name -> google.protobuf.Any ++ 35, // 54: envoy.config.route.v3.RouteAction.request_mirror_policies:type_name -> envoy.config.route.v3.RouteAction.RequestMirrorPolicy ++ 74, // 55: envoy.config.route.v3.RouteAction.priority:type_name -> envoy.config.core.v3.RoutingPriority ++ 22, // 56: envoy.config.route.v3.RouteAction.rate_limits:type_name -> envoy.config.route.v3.RateLimit ++ 68, // 57: envoy.config.route.v3.RouteAction.include_vh_rate_limits:type_name -> google.protobuf.BoolValue ++ 36, // 58: envoy.config.route.v3.RouteAction.hash_policy:type_name -> envoy.config.route.v3.RouteAction.HashPolicy ++ 12, // 59: envoy.config.route.v3.RouteAction.cors:type_name -> envoy.config.route.v3.CorsPolicy ++ 73, // 60: envoy.config.route.v3.RouteAction.max_grpc_timeout:type_name -> google.protobuf.Duration ++ 73, // 61: envoy.config.route.v3.RouteAction.grpc_timeout_offset:type_name -> google.protobuf.Duration ++ 37, // 62: envoy.config.route.v3.RouteAction.upgrade_configs:type_name -> envoy.config.route.v3.RouteAction.UpgradeConfig ++ 25, // 63: envoy.config.route.v3.RouteAction.internal_redirect_policy:type_name -> envoy.config.route.v3.InternalRedirectPolicy ++ 2, // 64: envoy.config.route.v3.RouteAction.internal_redirect_action:type_name -> envoy.config.route.v3.RouteAction.InternalRedirectAction ++ 64, // 65: envoy.config.route.v3.RouteAction.max_internal_redirects:type_name -> google.protobuf.UInt32Value ++ 15, // 66: envoy.config.route.v3.RouteAction.hedge_policy:type_name -> envoy.config.route.v3.HedgePolicy ++ 38, // 67: envoy.config.route.v3.RouteAction.max_stream_duration:type_name -> envoy.config.route.v3.RouteAction.MaxStreamDuration ++ 26, // 68: envoy.config.route.v3.RouteAction.internal_active_redirect_policy:type_name -> envoy.config.route.v3.InternalActiveRedirectPolicy ++ 64, // 69: envoy.config.route.v3.RetryPolicy.num_retries:type_name -> google.protobuf.UInt32Value ++ 73, // 70: envoy.config.route.v3.RetryPolicy.per_try_timeout:type_name -> google.protobuf.Duration ++ 73, // 71: envoy.config.route.v3.RetryPolicy.per_try_idle_timeout:type_name -> google.protobuf.Duration ++ 45, // 72: envoy.config.route.v3.RetryPolicy.retry_priority:type_name -> envoy.config.route.v3.RetryPolicy.RetryPriority ++ 46, // 73: envoy.config.route.v3.RetryPolicy.retry_host_predicate:type_name -> envoy.config.route.v3.RetryPolicy.RetryHostPredicate ++ 66, // 74: envoy.config.route.v3.RetryPolicy.retry_options_predicates:type_name -> envoy.config.core.v3.TypedExtensionConfig ++ 47, // 75: envoy.config.route.v3.RetryPolicy.retry_back_off:type_name -> envoy.config.route.v3.RetryPolicy.RetryBackOff ++ 49, // 76: envoy.config.route.v3.RetryPolicy.rate_limited_retry_back_off:type_name -> envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff ++ 23, // 77: envoy.config.route.v3.RetryPolicy.retriable_headers:type_name -> envoy.config.route.v3.HeaderMatcher ++ 23, // 78: envoy.config.route.v3.RetryPolicy.retriable_request_headers:type_name -> envoy.config.route.v3.HeaderMatcher ++ 64, // 79: envoy.config.route.v3.HedgePolicy.initial_requests:type_name -> google.protobuf.UInt32Value ++ 75, // 80: envoy.config.route.v3.HedgePolicy.additional_request_chance:type_name -> envoy.type.v3.FractionalPercent ++ 72, // 81: envoy.config.route.v3.RedirectAction.regex_rewrite:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute ++ 4, // 82: envoy.config.route.v3.RedirectAction.response_code:type_name -> envoy.config.route.v3.RedirectAction.RedirectResponseCode ++ 76, // 83: envoy.config.route.v3.DirectResponseAction.body:type_name -> envoy.config.core.v3.DataSource ++ 68, // 84: envoy.config.route.v3.Decorator.propagate:type_name -> google.protobuf.BoolValue ++ 75, // 85: envoy.config.route.v3.Tracing.client_sampling:type_name -> envoy.type.v3.FractionalPercent ++ 75, // 86: envoy.config.route.v3.Tracing.random_sampling:type_name -> envoy.type.v3.FractionalPercent ++ 75, // 87: envoy.config.route.v3.Tracing.overall_sampling:type_name -> envoy.type.v3.FractionalPercent ++ 77, // 88: envoy.config.route.v3.Tracing.custom_tags:type_name -> envoy.type.tracing.v3.CustomTag ++ 23, // 89: envoy.config.route.v3.VirtualCluster.headers:type_name -> envoy.config.route.v3.HeaderMatcher ++ 64, // 90: envoy.config.route.v3.RateLimit.stage:type_name -> google.protobuf.UInt32Value ++ 50, // 91: envoy.config.route.v3.RateLimit.actions:type_name -> envoy.config.route.v3.RateLimit.Action ++ 51, // 92: envoy.config.route.v3.RateLimit.limit:type_name -> envoy.config.route.v3.RateLimit.Override ++ 67, // 93: envoy.config.route.v3.HeaderMatcher.safe_regex_match:type_name -> envoy.type.matcher.v3.RegexMatcher ++ 78, // 94: envoy.config.route.v3.HeaderMatcher.range_match:type_name -> envoy.type.v3.Int64Range ++ 71, // 95: envoy.config.route.v3.HeaderMatcher.string_match:type_name -> envoy.type.matcher.v3.StringMatcher ++ 71, // 96: envoy.config.route.v3.QueryParameterMatcher.string_match:type_name -> envoy.type.matcher.v3.StringMatcher ++ 64, // 97: envoy.config.route.v3.InternalRedirectPolicy.max_internal_redirects:type_name -> google.protobuf.UInt32Value ++ 66, // 98: envoy.config.route.v3.InternalRedirectPolicy.predicates:type_name -> envoy.config.core.v3.TypedExtensionConfig ++ 64, // 99: envoy.config.route.v3.InternalActiveRedirectPolicy.max_internal_redirects:type_name -> google.protobuf.UInt32Value ++ 72, // 100: envoy.config.route.v3.InternalActiveRedirectPolicy.redirect_url_rewrite_regex:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute ++ 66, // 101: envoy.config.route.v3.InternalActiveRedirectPolicy.predicates:type_name -> envoy.config.core.v3.TypedExtensionConfig ++ 62, // 102: envoy.config.route.v3.InternalActiveRedirectPolicy.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 61, // 103: envoy.config.route.v3.InternalActiveRedirectPolicy.policies:type_name -> envoy.config.route.v3.InternalActiveRedirectPolicy.RedirectPolicy ++ 63, // 104: envoy.config.route.v3.FilterConfig.config:type_name -> google.protobuf.Any ++ 63, // 105: envoy.config.route.v3.VirtualHost.TypedPerFilterConfigEntry.value:type_name -> google.protobuf.Any ++ 63, // 106: envoy.config.route.v3.Route.TypedPerFilterConfigEntry.value:type_name -> google.protobuf.Any ++ 64, // 107: envoy.config.route.v3.WeightedCluster.ClusterWeight.weight:type_name -> google.protobuf.UInt32Value ++ 65, // 108: envoy.config.route.v3.WeightedCluster.ClusterWeight.metadata_match:type_name -> envoy.config.core.v3.Metadata ++ 62, // 109: envoy.config.route.v3.WeightedCluster.ClusterWeight.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 62, // 110: envoy.config.route.v3.WeightedCluster.ClusterWeight.response_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 31, // 111: envoy.config.route.v3.WeightedCluster.ClusterWeight.typed_per_filter_config:type_name -> envoy.config.route.v3.WeightedCluster.ClusterWeight.TypedPerFilterConfigEntry ++ 63, // 112: envoy.config.route.v3.WeightedCluster.ClusterWeight.TypedPerFilterConfigEntry.value:type_name -> google.protobuf.Any ++ 68, // 113: envoy.config.route.v3.RouteMatch.TlsContextMatchOptions.presented:type_name -> google.protobuf.BoolValue ++ 68, // 114: envoy.config.route.v3.RouteMatch.TlsContextMatchOptions.validated:type_name -> google.protobuf.BoolValue ++ 69, // 115: envoy.config.route.v3.RouteAction.RequestMirrorPolicy.runtime_fraction:type_name -> envoy.config.core.v3.RuntimeFractionalPercent ++ 68, // 116: envoy.config.route.v3.RouteAction.RequestMirrorPolicy.trace_sampled:type_name -> google.protobuf.BoolValue ++ 39, // 117: envoy.config.route.v3.RouteAction.HashPolicy.header:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.Header ++ 40, // 118: envoy.config.route.v3.RouteAction.HashPolicy.cookie:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.Cookie ++ 41, // 119: envoy.config.route.v3.RouteAction.HashPolicy.connection_properties:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.ConnectionProperties ++ 42, // 120: envoy.config.route.v3.RouteAction.HashPolicy.query_parameter:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.QueryParameter ++ 43, // 121: envoy.config.route.v3.RouteAction.HashPolicy.filter_state:type_name -> envoy.config.route.v3.RouteAction.HashPolicy.FilterState ++ 68, // 122: envoy.config.route.v3.RouteAction.UpgradeConfig.enabled:type_name -> google.protobuf.BoolValue ++ 44, // 123: envoy.config.route.v3.RouteAction.UpgradeConfig.connect_config:type_name -> envoy.config.route.v3.RouteAction.UpgradeConfig.ConnectConfig ++ 73, // 124: envoy.config.route.v3.RouteAction.MaxStreamDuration.max_stream_duration:type_name -> google.protobuf.Duration ++ 73, // 125: envoy.config.route.v3.RouteAction.MaxStreamDuration.grpc_timeout_header_max:type_name -> google.protobuf.Duration ++ 73, // 126: envoy.config.route.v3.RouteAction.MaxStreamDuration.grpc_timeout_header_offset:type_name -> google.protobuf.Duration ++ 72, // 127: envoy.config.route.v3.RouteAction.HashPolicy.Header.regex_rewrite:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute ++ 73, // 128: envoy.config.route.v3.RouteAction.HashPolicy.Cookie.ttl:type_name -> google.protobuf.Duration ++ 79, // 129: envoy.config.route.v3.RouteAction.UpgradeConfig.ConnectConfig.proxy_protocol_config:type_name -> envoy.config.core.v3.ProxyProtocolConfig ++ 63, // 130: envoy.config.route.v3.RetryPolicy.RetryPriority.typed_config:type_name -> google.protobuf.Any ++ 63, // 131: envoy.config.route.v3.RetryPolicy.RetryHostPredicate.typed_config:type_name -> google.protobuf.Any ++ 73, // 132: envoy.config.route.v3.RetryPolicy.RetryBackOff.base_interval:type_name -> google.protobuf.Duration ++ 73, // 133: envoy.config.route.v3.RetryPolicy.RetryBackOff.max_interval:type_name -> google.protobuf.Duration ++ 3, // 134: envoy.config.route.v3.RetryPolicy.ResetHeader.format:type_name -> envoy.config.route.v3.RetryPolicy.ResetHeaderFormat ++ 48, // 135: envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff.reset_headers:type_name -> envoy.config.route.v3.RetryPolicy.ResetHeader ++ 73, // 136: envoy.config.route.v3.RetryPolicy.RateLimitedRetryBackOff.max_interval:type_name -> google.protobuf.Duration ++ 52, // 137: envoy.config.route.v3.RateLimit.Action.source_cluster:type_name -> envoy.config.route.v3.RateLimit.Action.SourceCluster ++ 53, // 138: envoy.config.route.v3.RateLimit.Action.destination_cluster:type_name -> envoy.config.route.v3.RateLimit.Action.DestinationCluster ++ 54, // 139: envoy.config.route.v3.RateLimit.Action.request_headers:type_name -> envoy.config.route.v3.RateLimit.Action.RequestHeaders ++ 55, // 140: envoy.config.route.v3.RateLimit.Action.remote_address:type_name -> envoy.config.route.v3.RateLimit.Action.RemoteAddress ++ 56, // 141: envoy.config.route.v3.RateLimit.Action.generic_key:type_name -> envoy.config.route.v3.RateLimit.Action.GenericKey ++ 57, // 142: envoy.config.route.v3.RateLimit.Action.header_value_match:type_name -> envoy.config.route.v3.RateLimit.Action.HeaderValueMatch ++ 58, // 143: envoy.config.route.v3.RateLimit.Action.dynamic_metadata:type_name -> envoy.config.route.v3.RateLimit.Action.DynamicMetaData ++ 59, // 144: envoy.config.route.v3.RateLimit.Action.metadata:type_name -> envoy.config.route.v3.RateLimit.Action.MetaData ++ 66, // 145: envoy.config.route.v3.RateLimit.Action.extension:type_name -> envoy.config.core.v3.TypedExtensionConfig ++ 60, // 146: envoy.config.route.v3.RateLimit.Override.dynamic_metadata:type_name -> envoy.config.route.v3.RateLimit.Override.DynamicMetadata ++ 68, // 147: envoy.config.route.v3.RateLimit.Action.HeaderValueMatch.expect_match:type_name -> google.protobuf.BoolValue ++ 23, // 148: envoy.config.route.v3.RateLimit.Action.HeaderValueMatch.headers:type_name -> envoy.config.route.v3.HeaderMatcher ++ 80, // 149: envoy.config.route.v3.RateLimit.Action.DynamicMetaData.metadata_key:type_name -> envoy.type.metadata.v3.MetadataKey ++ 80, // 150: envoy.config.route.v3.RateLimit.Action.MetaData.metadata_key:type_name -> envoy.type.metadata.v3.MetadataKey ++ 5, // 151: envoy.config.route.v3.RateLimit.Action.MetaData.source:type_name -> envoy.config.route.v3.RateLimit.Action.MetaData.Source ++ 80, // 152: envoy.config.route.v3.RateLimit.Override.DynamicMetadata.metadata_key:type_name -> envoy.type.metadata.v3.MetadataKey ++ 64, // 153: envoy.config.route.v3.InternalActiveRedirectPolicy.RedirectPolicy.max_internal_redirects:type_name -> google.protobuf.UInt32Value ++ 72, // 154: envoy.config.route.v3.InternalActiveRedirectPolicy.RedirectPolicy.redirect_url_rewrite_regex:type_name -> envoy.type.matcher.v3.RegexMatchAndSubstitute ++ 66, // 155: envoy.config.route.v3.InternalActiveRedirectPolicy.RedirectPolicy.predicates:type_name -> envoy.config.core.v3.TypedExtensionConfig ++ 62, // 156: envoy.config.route.v3.InternalActiveRedirectPolicy.RedirectPolicy.request_headers_to_add:type_name -> envoy.config.core.v3.HeaderValueOption ++ 157, // [157:157] is the sub-list for method output_type ++ 157, // [157:157] is the sub-list for method input_type ++ 157, // [157:157] is the sub-list for extension type_name ++ 157, // [157:157] is the sub-list for extension extendee ++ 0, // [0:157] is the sub-list for field type_name + } + + func init() { file_envoy_config_route_v3_route_components_proto_init() } +@@ -7353,7 +7966,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*RouteMatch); i { ++ switch v := v.(*ClusterSpecifierPlugin); i { + case 0: + return &v.state + case 1: +@@ -7365,7 +7978,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*CorsPolicy); i { ++ switch v := v.(*RouteMatch); i { + case 0: + return &v.state + case 1: +@@ -7377,7 +7990,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*RouteAction); i { ++ switch v := v.(*CorsPolicy); i { + case 0: + return &v.state + case 1: +@@ -7389,7 +8002,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*RetryPolicy); i { ++ switch v := v.(*RouteAction); i { + case 0: + return &v.state + case 1: +@@ -7401,7 +8014,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*HedgePolicy); i { ++ switch v := v.(*RetryPolicy); i { + case 0: + return &v.state + case 1: +@@ -7413,7 +8026,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*RedirectAction); i { ++ switch v := v.(*HedgePolicy); i { + case 0: + return &v.state + case 1: +@@ -7425,7 +8038,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*DirectResponseAction); i { ++ switch v := v.(*RedirectAction); i { + case 0: + return &v.state + case 1: +@@ -7437,7 +8050,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*NonForwardingAction); i { ++ switch v := v.(*DirectResponseAction); i { + case 0: + return &v.state + case 1: +@@ -7449,7 +8062,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*Decorator); i { ++ switch v := v.(*NonForwardingAction); i { + case 0: + return &v.state + case 1: +@@ -7461,7 +8074,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*Tracing); i { ++ switch v := v.(*Decorator); i { + case 0: + return &v.state + case 1: +@@ -7473,7 +8086,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*VirtualCluster); i { ++ switch v := v.(*Tracing); i { + case 0: + return &v.state + case 1: +@@ -7485,7 +8098,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*RateLimit); i { ++ switch v := v.(*VirtualCluster); i { + case 0: + return &v.state + case 1: +@@ -7497,7 +8110,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*HeaderMatcher); i { ++ switch v := v.(*RateLimit); i { + case 0: + return &v.state + case 1: +@@ -7509,7 +8122,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*QueryParameterMatcher); i { ++ switch v := v.(*HeaderMatcher); i { + case 0: + return &v.state + case 1: +@@ -7521,7 +8134,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { +- switch v := v.(*InternalRedirectPolicy); i { ++ switch v := v.(*QueryParameterMatcher); i { + case 0: + return &v.state + case 1: +@@ -7533,6 +8146,30 @@ func file_envoy_config_route_v3_route_components_proto_init() { + } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*InternalRedirectPolicy); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_envoy_config_route_v3_route_components_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*InternalActiveRedirectPolicy); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } ++ file_envoy_config_route_v3_route_components_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FilterConfig); i { + case 0: + return &v.state +@@ -7544,7 +8181,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WeightedCluster_ClusterWeight); i { + case 0: + return &v.state +@@ -7556,7 +8193,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteMatch_GrpcRouteMatchOptions); i { + case 0: + return &v.state +@@ -7568,7 +8205,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteMatch_TlsContextMatchOptions); i { + case 0: + return &v.state +@@ -7580,7 +8217,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteMatch_ConnectMatcher); i { + case 0: + return &v.state +@@ -7592,7 +8229,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_RequestMirrorPolicy); i { + case 0: + return &v.state +@@ -7604,7 +8241,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_HashPolicy); i { + case 0: + return &v.state +@@ -7616,7 +8253,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_UpgradeConfig); i { + case 0: + return &v.state +@@ -7628,7 +8265,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_MaxStreamDuration); i { + case 0: + return &v.state +@@ -7640,7 +8277,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_HashPolicy_Header); i { + case 0: + return &v.state +@@ -7652,7 +8289,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_HashPolicy_Cookie); i { + case 0: + return &v.state +@@ -7664,7 +8301,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_HashPolicy_ConnectionProperties); i { + case 0: + return &v.state +@@ -7676,7 +8313,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_HashPolicy_QueryParameter); i { + case 0: + return &v.state +@@ -7688,7 +8325,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_HashPolicy_FilterState); i { + case 0: + return &v.state +@@ -7700,7 +8337,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteAction_UpgradeConfig_ConnectConfig); i { + case 0: + return &v.state +@@ -7712,7 +8349,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RetryPolicy_RetryPriority); i { + case 0: + return &v.state +@@ -7724,7 +8361,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RetryPolicy_RetryHostPredicate); i { + case 0: + return &v.state +@@ -7736,7 +8373,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RetryPolicy_RetryBackOff); i { + case 0: + return &v.state +@@ -7748,7 +8385,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RetryPolicy_ResetHeader); i { + case 0: + return &v.state +@@ -7760,7 +8397,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RetryPolicy_RateLimitedRetryBackOff); i { + case 0: + return &v.state +@@ -7772,7 +8409,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action); i { + case 0: + return &v.state +@@ -7784,7 +8421,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Override); i { + case 0: + return &v.state +@@ -7796,7 +8433,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_SourceCluster); i { + case 0: + return &v.state +@@ -7808,7 +8445,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_DestinationCluster); i { + case 0: + return &v.state +@@ -7820,7 +8457,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_RequestHeaders); i { + case 0: + return &v.state +@@ -7832,7 +8469,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_RemoteAddress); i { + case 0: + return &v.state +@@ -7844,7 +8481,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_GenericKey); i { + case 0: + return &v.state +@@ -7856,7 +8493,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_HeaderValueMatch); i { + case 0: + return &v.state +@@ -7868,7 +8505,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_DynamicMetaData); i { + case 0: + return &v.state +@@ -7880,7 +8517,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Action_MetaData); i { + case 0: + return &v.state +@@ -7892,7 +8529,7 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { ++ file_envoy_config_route_v3_route_components_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimit_Override_DynamicMetadata); i { + case 0: + return &v.state +@@ -7904,6 +8541,18 @@ func file_envoy_config_route_v3_route_components_proto_init() { + return nil + } + } ++ file_envoy_config_route_v3_route_components_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { ++ switch v := v.(*InternalActiveRedirectPolicy_RedirectPolicy); i { ++ case 0: ++ return &v.state ++ case 1: ++ return &v.sizeCache ++ case 2: ++ return &v.unknownFields ++ default: ++ return nil ++ } ++ } + } + file_envoy_config_route_v3_route_components_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*Route_Route)(nil), +@@ -7912,33 +8561,34 @@ func file_envoy_config_route_v3_route_components_proto_init() { + (*Route_FilterAction)(nil), + (*Route_NonForwardingAction)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[4].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*RouteMatch_Prefix)(nil), + (*RouteMatch_Path)(nil), + (*RouteMatch_SafeRegex)(nil), + (*RouteMatch_ConnectMatcher_)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[5].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[6].OneofWrappers = []interface{}{ + (*CorsPolicy_FilterEnabled)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[6].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[7].OneofWrappers = []interface{}{ + (*RouteAction_Cluster)(nil), + (*RouteAction_ClusterHeader)(nil), + (*RouteAction_WeightedClusters)(nil), + (*RouteAction_ClusterSpecifierPlugin)(nil), ++ (*RouteAction_InlineClusterSpecifierPlugin)(nil), + (*RouteAction_HostRewriteLiteral)(nil), + (*RouteAction_AutoHostRewrite)(nil), + (*RouteAction_HostRewriteHeader)(nil), + (*RouteAction_HostRewritePathRegex)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[9].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[10].OneofWrappers = []interface{}{ + (*RedirectAction_HttpsRedirect)(nil), + (*RedirectAction_SchemeRedirect)(nil), + (*RedirectAction_PathRedirect)(nil), + (*RedirectAction_PrefixRewrite)(nil), + (*RedirectAction_RegexRewrite)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[16].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[17].OneofWrappers = []interface{}{ + (*HeaderMatcher_ExactMatch)(nil), + (*HeaderMatcher_SafeRegexMatch)(nil), + (*HeaderMatcher_RangeMatch)(nil), +@@ -7948,27 +8598,31 @@ func file_envoy_config_route_v3_route_components_proto_init() { + (*HeaderMatcher_ContainsMatch)(nil), + (*HeaderMatcher_StringMatch)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[17].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[18].OneofWrappers = []interface{}{ + (*QueryParameterMatcher_StringMatch)(nil), + (*QueryParameterMatcher_PresentMatch)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[22].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[20].OneofWrappers = []interface{}{ ++ (*InternalActiveRedirectPolicy_RedirectUrl)(nil), ++ (*InternalActiveRedirectPolicy_RedirectUrlRewriteRegex)(nil), ++ } ++ file_envoy_config_route_v3_route_components_proto_msgTypes[24].OneofWrappers = []interface{}{ + (*WeightedCluster_ClusterWeight_HostRewriteLiteral)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[28].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[30].OneofWrappers = []interface{}{ + (*RouteAction_HashPolicy_Header_)(nil), + (*RouteAction_HashPolicy_Cookie_)(nil), + (*RouteAction_HashPolicy_ConnectionProperties_)(nil), + (*RouteAction_HashPolicy_QueryParameter_)(nil), + (*RouteAction_HashPolicy_FilterState_)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[37].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[39].OneofWrappers = []interface{}{ + (*RetryPolicy_RetryPriority_TypedConfig)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[38].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[40].OneofWrappers = []interface{}{ + (*RetryPolicy_RetryHostPredicate_TypedConfig)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[42].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[44].OneofWrappers = []interface{}{ + (*RateLimit_Action_SourceCluster_)(nil), + (*RateLimit_Action_DestinationCluster_)(nil), + (*RateLimit_Action_RequestHeaders_)(nil), +@@ -7979,16 +8633,20 @@ func file_envoy_config_route_v3_route_components_proto_init() { + (*RateLimit_Action_Metadata)(nil), + (*RateLimit_Action_Extension)(nil), + } +- file_envoy_config_route_v3_route_components_proto_msgTypes[43].OneofWrappers = []interface{}{ ++ file_envoy_config_route_v3_route_components_proto_msgTypes[45].OneofWrappers = []interface{}{ + (*RateLimit_Override_DynamicMetadata_)(nil), + } ++ file_envoy_config_route_v3_route_components_proto_msgTypes[55].OneofWrappers = []interface{}{ ++ (*InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrl)(nil), ++ (*InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteRegex)(nil), ++ } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_envoy_config_route_v3_route_components_proto_rawDesc, + NumEnums: 6, +- NumMessages: 53, ++ NumMessages: 56, + NumExtensions: 0, + NumServices: 0, + }, +diff --git a/envoy/config/route/v3/route_components.pb.validate.go b/envoy/config/route/v3/route_components.pb.validate.go +index c2da6c96..6a474275 100755 +--- a/envoy/config/route/v3/route_components.pb.validate.go ++++ b/envoy/config/route/v3/route_components.pb.validate.go +@@ -753,6 +753,18 @@ func (m *WeightedCluster) Validate() error { + + // no validation rules for RuntimeKeyPrefix + ++ // no validation rules for ClusterSpecifierPlugin ++ ++ if v, ok := interface{}(m.GetInlineClusterSpecifierPlugin()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return WeightedClusterValidationError{ ++ field: "InlineClusterSpecifierPlugin", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ + return nil + } + +@@ -810,6 +822,92 @@ var _ interface { + ErrorName() string + } = WeightedClusterValidationError{} + ++// Validate checks the field values on ClusterSpecifierPlugin with the rules ++// defined in the proto definition for this message. If any rules are ++// violated, an error is returned. ++func (m *ClusterSpecifierPlugin) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if m.GetExtension() == nil { ++ return ClusterSpecifierPluginValidationError{ ++ field: "Extension", ++ reason: "value is required", ++ } ++ } ++ ++ if v, ok := interface{}(m.GetExtension()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return ClusterSpecifierPluginValidationError{ ++ field: "Extension", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ // no validation rules for IsOptional ++ ++ return nil ++} ++ ++// ClusterSpecifierPluginValidationError is the validation error returned by ++// ClusterSpecifierPlugin.Validate if the designated constraints aren't met. ++type ClusterSpecifierPluginValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e ClusterSpecifierPluginValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e ClusterSpecifierPluginValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e ClusterSpecifierPluginValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e ClusterSpecifierPluginValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e ClusterSpecifierPluginValidationError) ErrorName() string { ++ return "ClusterSpecifierPluginValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e ClusterSpecifierPluginValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sClusterSpecifierPlugin.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = ClusterSpecifierPluginValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = ClusterSpecifierPluginValidationError{} ++ + // Validate checks the field values on RouteMatch with the rules defined in the + // proto definition for this message. If any rules are violated, an error is returned. + func (m *RouteMatch) Validate() error { +@@ -1360,6 +1458,16 @@ func (m *RouteAction) Validate() error { + } + } + ++ if v, ok := interface{}(m.GetInternalActiveRedirectPolicy()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return RouteActionValidationError{ ++ field: "InternalActiveRedirectPolicy", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ + switch m.ClusterSpecifier.(type) { + + case *RouteAction_Cluster: +@@ -1402,6 +1510,18 @@ func (m *RouteAction) Validate() error { + case *RouteAction_ClusterSpecifierPlugin: + // no validation rules for ClusterSpecifierPlugin + ++ case *RouteAction_InlineClusterSpecifierPlugin: ++ ++ if v, ok := interface{}(m.GetInlineClusterSpecifierPlugin()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return RouteActionValidationError{ ++ field: "InlineClusterSpecifierPlugin", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ + default: + return RouteActionValidationError{ + field: "ClusterSpecifier", +@@ -2832,6 +2952,183 @@ var _ interface { + ErrorName() string + } = InternalRedirectPolicyValidationError{} + ++// Validate checks the field values on InternalActiveRedirectPolicy with the ++// rules defined in the proto definition for this message. If any rules are ++// violated, an error is returned. ++func (m *InternalActiveRedirectPolicy) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if v, ok := interface{}(m.GetMaxInternalRedirects()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: "MaxInternalRedirects", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ if len(m.GetRedirectResponseCodes()) > 50 { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: "RedirectResponseCodes", ++ reason: "value must contain no more than 50 item(s)", ++ } ++ } ++ ++ for idx, item := range m.GetPredicates() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: fmt.Sprintf("Predicates[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ // no validation rules for AllowCrossSchemeRedirect ++ ++ if len(m.GetRequestHeadersToAdd()) > 1000 { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: "RequestHeadersToAdd", ++ reason: "value must contain no more than 1000 item(s)", ++ } ++ } ++ ++ for idx, item := range m.GetRequestHeadersToAdd() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: fmt.Sprintf("RequestHeadersToAdd[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ if !_InternalActiveRedirectPolicy_HostRewriteLiteral_Pattern.MatchString(m.GetHostRewriteLiteral()) { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: "HostRewriteLiteral", ++ reason: "value does not match regex pattern \"^[^\\x00\\n\\r]*$\"", ++ } ++ } ++ ++ // no validation rules for ForcedUseOriginalHost ++ ++ // no validation rules for ForcedAddHeaderBeforeRouteMatcher ++ ++ for idx, item := range m.GetPolicies() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: fmt.Sprintf("Policies[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ switch m.RedirectUrlRewriteSpecifier.(type) { ++ ++ case *InternalActiveRedirectPolicy_RedirectUrl: ++ ++ if utf8.RuneCountInString(m.GetRedirectUrl()) < 1 { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: "RedirectUrl", ++ reason: "value length must be at least 1 runes", ++ } ++ } ++ ++ case *InternalActiveRedirectPolicy_RedirectUrlRewriteRegex: ++ ++ if v, ok := interface{}(m.GetRedirectUrlRewriteRegex()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicyValidationError{ ++ field: "RedirectUrlRewriteRegex", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ return nil ++} ++ ++// InternalActiveRedirectPolicyValidationError is the validation error returned ++// by InternalActiveRedirectPolicy.Validate if the designated constraints ++// aren't met. ++type InternalActiveRedirectPolicyValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e InternalActiveRedirectPolicyValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e InternalActiveRedirectPolicyValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e InternalActiveRedirectPolicyValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e InternalActiveRedirectPolicyValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e InternalActiveRedirectPolicyValidationError) ErrorName() string { ++ return "InternalActiveRedirectPolicyValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e InternalActiveRedirectPolicyValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sInternalActiveRedirectPolicy.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = InternalActiveRedirectPolicyValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = InternalActiveRedirectPolicyValidationError{} ++ ++var _InternalActiveRedirectPolicy_HostRewriteLiteral_Pattern = regexp.MustCompile("^[^\x00\n\r]*$") ++ + // Validate checks the field values on FilterConfig with the rules defined in + // the proto definition for this message. If any rules are violated, an error + // is returned. +@@ -5780,3 +6077,171 @@ var _ interface { + Cause() error + ErrorName() string + } = RateLimit_Override_DynamicMetadataValidationError{} ++ ++// Validate checks the field values on ++// InternalActiveRedirectPolicy_RedirectPolicy with the rules defined in the ++// proto definition for this message. If any rules are violated, an error is returned. ++func (m *InternalActiveRedirectPolicy_RedirectPolicy) Validate() error { ++ if m == nil { ++ return nil ++ } ++ ++ if v, ok := interface{}(m.GetMaxInternalRedirects()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: "MaxInternalRedirects", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ if len(m.GetRedirectResponseCodes()) > 50 { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: "RedirectResponseCodes", ++ reason: "value must contain no more than 50 item(s)", ++ } ++ } ++ ++ for idx, item := range m.GetPredicates() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: fmt.Sprintf("Predicates[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ // no validation rules for AllowCrossSchemeRedirect ++ ++ if len(m.GetRequestHeadersToAdd()) > 1000 { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: "RequestHeadersToAdd", ++ reason: "value must contain no more than 1000 item(s)", ++ } ++ } ++ ++ for idx, item := range m.GetRequestHeadersToAdd() { ++ _, _ = idx, item ++ ++ if v, ok := interface{}(item).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: fmt.Sprintf("RequestHeadersToAdd[%v]", idx), ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ } ++ ++ if !_InternalActiveRedirectPolicy_RedirectPolicy_HostRewriteLiteral_Pattern.MatchString(m.GetHostRewriteLiteral()) { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: "HostRewriteLiteral", ++ reason: "value does not match regex pattern \"^[^\\x00\\n\\r]*$\"", ++ } ++ } ++ ++ // no validation rules for ForcedUseOriginalHost ++ ++ // no validation rules for ForcedAddHeaderBeforeRouteMatcher ++ ++ switch m.RedirectUrlRewriteSpecifier.(type) { ++ ++ case *InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrl: ++ ++ if utf8.RuneCountInString(m.GetRedirectUrl()) < 1 { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: "RedirectUrl", ++ reason: "value length must be at least 1 runes", ++ } ++ } ++ ++ case *InternalActiveRedirectPolicy_RedirectPolicy_RedirectUrlRewriteRegex: ++ ++ if v, ok := interface{}(m.GetRedirectUrlRewriteRegex()).(interface{ Validate() error }); ok { ++ if err := v.Validate(); err != nil { ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: "RedirectUrlRewriteRegex", ++ reason: "embedded message failed validation", ++ cause: err, ++ } ++ } ++ } ++ ++ default: ++ return InternalActiveRedirectPolicy_RedirectPolicyValidationError{ ++ field: "RedirectUrlRewriteSpecifier", ++ reason: "value is required", ++ } ++ ++ } ++ ++ return nil ++} ++ ++// InternalActiveRedirectPolicy_RedirectPolicyValidationError is the validation ++// error returned by InternalActiveRedirectPolicy_RedirectPolicy.Validate if ++// the designated constraints aren't met. ++type InternalActiveRedirectPolicy_RedirectPolicyValidationError struct { ++ field string ++ reason string ++ cause error ++ key bool ++} ++ ++// Field function returns field value. ++func (e InternalActiveRedirectPolicy_RedirectPolicyValidationError) Field() string { return e.field } ++ ++// Reason function returns reason value. ++func (e InternalActiveRedirectPolicy_RedirectPolicyValidationError) Reason() string { return e.reason } ++ ++// Cause function returns cause value. ++func (e InternalActiveRedirectPolicy_RedirectPolicyValidationError) Cause() error { return e.cause } ++ ++// Key function returns key value. ++func (e InternalActiveRedirectPolicy_RedirectPolicyValidationError) Key() bool { return e.key } ++ ++// ErrorName returns error name. ++func (e InternalActiveRedirectPolicy_RedirectPolicyValidationError) ErrorName() string { ++ return "InternalActiveRedirectPolicy_RedirectPolicyValidationError" ++} ++ ++// Error satisfies the builtin error interface ++func (e InternalActiveRedirectPolicy_RedirectPolicyValidationError) Error() string { ++ cause := "" ++ if e.cause != nil { ++ cause = fmt.Sprintf(" | caused by: %v", e.cause) ++ } ++ ++ key := "" ++ if e.key { ++ key = "key for " ++ } ++ ++ return fmt.Sprintf( ++ "invalid %sInternalActiveRedirectPolicy_RedirectPolicy.%s: %s%s", ++ key, ++ e.field, ++ e.reason, ++ cause) ++} ++ ++var _ error = InternalActiveRedirectPolicy_RedirectPolicyValidationError{} ++ ++var _ interface { ++ Field() string ++ Reason() string ++ Key() bool ++ Cause() error ++ ErrorName() string ++} = InternalActiveRedirectPolicy_RedirectPolicyValidationError{} ++ ++var _InternalActiveRedirectPolicy_RedirectPolicy_HostRewriteLiteral_Pattern = regexp.MustCompile("^[^\x00\n\r]*$")