Imported Upstream version 1.21.0
[platform/upstream/grpc.git] / src / core / ext / filters / client_channel / service_config.h
1 //
2 // Copyright 2016 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_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H
18 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H
19
20 #include <grpc/support/port_platform.h>
21
22 #include <grpc/impl/codegen/grpc_types.h>
23 #include <grpc/support/string_util.h>
24
25 #include "src/core/lib/gprpp/inlined_vector.h"
26 #include "src/core/lib/gprpp/ref_counted.h"
27 #include "src/core/lib/gprpp/ref_counted_ptr.h"
28 #include "src/core/lib/iomgr/error.h"
29 #include "src/core/lib/json/json.h"
30 #include "src/core/lib/slice/slice_hash_table.h"
31
32 // The main purpose of the code here is to parse the service config in
33 // JSON form, which will look like this:
34 //
35 // {
36 //   "loadBalancingPolicy": "string",  // optional
37 //   "methodConfig": [  // array of one or more method_config objects
38 //     {
39 //       "name": [  // array of one or more name objects
40 //         {
41 //           "service": "string",  // required
42 //           "method": "string",  // optional
43 //         }
44 //       ],
45 //       // remaining fields are optional.
46 //       // see https://developers.google.com/protocol-buffers/docs/proto3#json
47 //       // for format details.
48 //       "waitForReady": bool,
49 //       "timeout": "duration_string",
50 //       "maxRequestMessageBytes": "int64_string",
51 //       "maxResponseMessageBytes": "int64_string",
52 //     }
53 //   ]
54 // }
55
56 namespace grpc_core {
57
58 class ServiceConfig : public RefCounted<ServiceConfig> {
59  public:
60   /// This is the base class that all service config parsers MUST use to store
61   /// parsed service config data.
62   class ParsedConfig {
63    public:
64     virtual ~ParsedConfig() = default;
65
66     GRPC_ABSTRACT_BASE_CLASS;
67   };
68
69   /// This is the base class that all service config parsers should derive from.
70   class Parser {
71    public:
72     virtual ~Parser() = default;
73
74     virtual UniquePtr<ParsedConfig> ParseGlobalParams(const grpc_json* json,
75                                                       grpc_error** error) {
76       GPR_DEBUG_ASSERT(error != nullptr);
77       return nullptr;
78     }
79
80     virtual UniquePtr<ParsedConfig> ParsePerMethodParams(const grpc_json* json,
81                                                          grpc_error** error) {
82       GPR_DEBUG_ASSERT(error != nullptr);
83       return nullptr;
84     }
85
86     GRPC_ABSTRACT_BASE_CLASS;
87   };
88
89   static constexpr int kNumPreallocatedParsers = 4;
90   typedef InlinedVector<UniquePtr<ParsedConfig>, kNumPreallocatedParsers>
91       ServiceConfigObjectsVector;
92
93   /// When a service config is applied to a call in the client_channel_filter,
94   /// we create an instance of this object and store it in the call_data for
95   /// client_channel. A pointer to this object is also stored in the
96   /// call_context, so that future filters can easily access method and global
97   /// parameters for the call.
98   class CallData {
99    public:
100     CallData() = default;
101     CallData(RefCountedPtr<ServiceConfig> svc_cfg, const grpc_slice& path)
102         : service_config_(std::move(svc_cfg)) {
103       if (service_config_ != nullptr) {
104         method_params_vector_ =
105             service_config_->GetMethodServiceConfigObjectsVector(path);
106       }
107     }
108
109     ServiceConfig* service_config() { return service_config_.get(); }
110
111     ParsedConfig* GetMethodParsedObject(size_t index) const {
112       return method_params_vector_ != nullptr
113                  ? (*method_params_vector_)[index].get()
114                  : nullptr;
115     }
116
117     ParsedConfig* GetGlobalParsedObject(size_t index) const {
118       return service_config_->GetParsedGlobalServiceConfigObject(index);
119     }
120
121    private:
122     RefCountedPtr<ServiceConfig> service_config_;
123     const ServiceConfigObjectsVector* method_params_vector_ = nullptr;
124   };
125
126   /// Creates a new service config from parsing \a json_string.
127   /// Returns null on parse error.
128   static RefCountedPtr<ServiceConfig> Create(const char* json,
129                                              grpc_error** error);
130
131   ~ServiceConfig();
132
133   const char* service_config_json() const { return service_config_json_.get(); }
134
135   /// Retrieves the parsed global service config object at index \a index. The
136   /// lifetime of the returned object is tied to the lifetime of the
137   /// ServiceConfig object.
138   ParsedConfig* GetParsedGlobalServiceConfigObject(size_t index) {
139     GPR_DEBUG_ASSERT(index < parsed_global_service_config_objects_.size());
140     return parsed_global_service_config_objects_[index].get();
141   }
142
143   /// Retrieves the vector of method service config objects for a given path \a
144   /// path. The lifetime of the returned vector and contained objects is tied to
145   /// the lifetime of the ServiceConfig object.
146   const ServiceConfigObjectsVector* GetMethodServiceConfigObjectsVector(
147       const grpc_slice& path);
148
149   /// Globally register a service config parser. On successful registration, it
150   /// returns the index at which the parser was registered. On failure, -1 is
151   /// returned. Each new service config update will go through all the
152   /// registered parser. Each parser is responsible for reading the service
153   /// config json and returning a parsed object. This parsed object can later be
154   /// retrieved using the same index that was returned at registration time.
155   static size_t RegisterParser(UniquePtr<Parser> parser);
156
157   static void Init();
158
159   static void Shutdown();
160
161  private:
162   // So New() can call our private ctor.
163   template <typename T, typename... Args>
164   friend T* New(Args&&... args);
165
166   // Takes ownership of \a json_tree.
167   ServiceConfig(UniquePtr<char> service_config_json,
168                 UniquePtr<char> json_string, grpc_json* json_tree,
169                 grpc_error** error);
170
171   // Helper functions to parse the service config
172   grpc_error* ParseGlobalParams(const grpc_json* json_tree);
173   grpc_error* ParsePerMethodParams(const grpc_json* json_tree);
174
175   // Returns the number of names specified in the method config \a json.
176   static int CountNamesInMethodConfig(grpc_json* json);
177
178   // Returns a path string for the JSON name object specified by \a json.
179   // Returns null on error, and stores error in \a error.
180   static UniquePtr<char> ParseJsonMethodName(grpc_json* json,
181                                              grpc_error** error);
182
183   grpc_error* ParseJsonMethodConfigToServiceConfigObjectsTable(
184       const grpc_json* json,
185       SliceHashTable<const ServiceConfigObjectsVector*>::Entry* entries,
186       size_t* idx);
187
188   UniquePtr<char> service_config_json_;
189   UniquePtr<char> json_string_;  // Underlying storage for json_tree.
190   grpc_json* json_tree_;
191
192   InlinedVector<UniquePtr<ParsedConfig>, kNumPreallocatedParsers>
193       parsed_global_service_config_objects_;
194   // A map from the method name to the service config objects vector. Note that
195   // we are using a raw pointer and not a unique pointer so that we can use the
196   // same vector for multiple names.
197   RefCountedPtr<SliceHashTable<const ServiceConfigObjectsVector*>>
198       parsed_method_service_config_objects_table_;
199   // Storage for all the vectors that are being used in
200   // parsed_method_service_config_objects_table_.
201   InlinedVector<UniquePtr<ServiceConfigObjectsVector>, 32>
202       service_config_objects_vectors_storage_;
203 };
204
205 }  // namespace grpc_core
206
207 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H */