1 // 2 // Copyright 2020 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SRC_CORE_CLIENT_CHANNEL_CONFIG_SELECTOR_H 18 #define GRPC_SRC_CORE_CLIENT_CHANNEL_CONFIG_SELECTOR_H 19 20 #include <grpc/grpc.h> 21 #include <grpc/support/port_platform.h> 22 #include <string.h> 23 24 #include <utility> 25 #include <vector> 26 27 #include "absl/log/check.h" 28 #include "absl/status/status.h" 29 #include "absl/strings/string_view.h" 30 #include "src/core/client_channel/client_channel_internal.h" 31 #include "src/core/lib/channel/channel_fwd.h" 32 #include "src/core/lib/resource_quota/arena.h" 33 #include "src/core/lib/slice/slice.h" 34 #include "src/core/lib/transport/interception_chain.h" 35 #include "src/core/lib/transport/metadata_batch.h" 36 #include "src/core/service_config/service_config.h" 37 #include "src/core/util/ref_counted.h" 38 #include "src/core/util/ref_counted_ptr.h" 39 #include "src/core/util/unique_type_name.h" 40 #include "src/core/util/useful.h" 41 42 // Channel arg key for ConfigSelector. 43 #define GRPC_ARG_CONFIG_SELECTOR "grpc.internal.config_selector" 44 45 namespace grpc_core { 46 47 // Internal API used to allow resolver implementations to override 48 // MethodConfig and provide input to LB policies on a per-call basis. 49 class ConfigSelector : public RefCounted<ConfigSelector> { 50 public: 51 ~ConfigSelector() override = default; 52 53 virtual UniqueTypeName name() const = 0; 54 Equals(const ConfigSelector * cs1,const ConfigSelector * cs2)55 static bool Equals(const ConfigSelector* cs1, const ConfigSelector* cs2) { 56 if (cs1 == nullptr) return cs2 == nullptr; 57 if (cs2 == nullptr) return false; 58 if (cs1->name() != cs2->name()) return false; 59 return cs1->Equals(cs2); 60 } 61 62 // The channel will call this when the resolver returns a new ConfigSelector 63 // to determine what set of dynamic filters will be configured. AddFilters(InterceptionChainBuilder &)64 virtual void AddFilters(InterceptionChainBuilder& /*builder*/) {} 65 // TODO(roth): Remove this once the legacy filter stack goes away. GetFilters()66 virtual std::vector<const grpc_channel_filter*> GetFilters() { return {}; } 67 68 // Gets the configuration for the call and stores it in service config 69 // call data. 70 struct GetCallConfigArgs { 71 grpc_metadata_batch* initial_metadata; 72 Arena* arena; 73 ClientChannelServiceConfigCallData* service_config_call_data; 74 }; 75 virtual absl::Status GetCallConfig(GetCallConfigArgs args) = 0; 76 ChannelArgName()77 static absl::string_view ChannelArgName() { return GRPC_ARG_CONFIG_SELECTOR; } ChannelArgsCompare(const ConfigSelector * a,const ConfigSelector * b)78 static int ChannelArgsCompare(const ConfigSelector* a, 79 const ConfigSelector* b) { 80 return QsortCompare(a, b); 81 } 82 83 private: 84 // Will be called only if the two objects have the same name, so 85 // subclasses can be free to safely down-cast the argument. 86 virtual bool Equals(const ConfigSelector* other) const = 0; 87 }; 88 89 // Default ConfigSelector that gets the MethodConfig from the service config. 90 class DefaultConfigSelector final : public ConfigSelector { 91 public: DefaultConfigSelector(RefCountedPtr<ServiceConfig> service_config)92 explicit DefaultConfigSelector(RefCountedPtr<ServiceConfig> service_config) 93 : service_config_(std::move(service_config)) { 94 // The client channel code ensures that this will never be null. 95 // If neither the resolver nor the client application provide a 96 // config, a default empty config will be used. 97 DCHECK(service_config_ != nullptr); 98 } 99 name()100 UniqueTypeName name() const override { 101 static UniqueTypeName::Factory kFactory("default"); 102 return kFactory.Create(); 103 } 104 GetCallConfig(GetCallConfigArgs args)105 absl::Status GetCallConfig(GetCallConfigArgs args) override { 106 Slice* path = args.initial_metadata->get_pointer(HttpPathMetadata()); 107 CHECK_NE(path, nullptr); 108 auto* parsed_method_configs = 109 service_config_->GetMethodParsedConfigVector(path->c_slice()); 110 args.service_config_call_data->SetServiceConfig(service_config_, 111 parsed_method_configs); 112 return absl::OkStatus(); 113 } 114 115 // Only comparing the ConfigSelector itself, not the underlying 116 // service config, so we always return true. Equals(const ConfigSelector *)117 bool Equals(const ConfigSelector* /*other*/) const override { return true; } 118 119 private: 120 RefCountedPtr<ServiceConfig> service_config_; 121 }; 122 123 } // namespace grpc_core 124 125 #endif // GRPC_SRC_CORE_CLIENT_CHANNEL_CONFIG_SELECTOR_H 126