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_SRC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H
18 #define GRPC_SRC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H
19 
20 #include <grpc/support/port_platform.h>
21 
22 #include <stddef.h>
23 
24 #include <memory>
25 #include <utility>
26 
27 #include "src/core/lib/channel/context.h"
28 #include "src/core/lib/gprpp/chunked_vector.h"
29 #include "src/core/lib/gprpp/ref_counted_ptr.h"
30 #include "src/core/lib/gprpp/unique_type_name.h"
31 #include "src/core/lib/resource_quota/arena.h"
32 #include "src/core/lib/service_config/service_config.h"
33 #include "src/core/lib/service_config/service_config_parser.h"
34 
35 namespace grpc_core {
36 
37 /// Stores the service config data associated with an individual call.
38 /// A pointer to this object is stored in the call_context
39 /// GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA element, so that filters can
40 /// easily access method and global parameters for the call.
41 ///
42 /// Must be accessed when holding the call combiner (legacy filter) or from
43 /// inside the activity (promise-based filter).
44 class ServiceConfigCallData {
45  public:
46   class CallAttributeInterface {
47    public:
48     virtual ~CallAttributeInterface() = default;
49     virtual UniqueTypeName type() const = 0;
50   };
51 
ServiceConfigCallData(Arena * arena,grpc_call_context_element * call_context)52   ServiceConfigCallData(Arena* arena, grpc_call_context_element* call_context)
53       : call_attributes_(arena) {
54     call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
55     call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
56   }
57 
58   virtual ~ServiceConfigCallData() = default;
59 
SetServiceConfig(RefCountedPtr<ServiceConfig> service_config,const ServiceConfigParser::ParsedConfigVector * method_configs)60   void SetServiceConfig(
61       RefCountedPtr<ServiceConfig> service_config,
62       const ServiceConfigParser::ParsedConfigVector* method_configs) {
63     service_config_ = std::move(service_config);
64     method_configs_ = method_configs;
65   }
66 
service_config()67   ServiceConfig* service_config() { return service_config_.get(); }
68 
GetMethodParsedConfig(size_t index)69   ServiceConfigParser::ParsedConfig* GetMethodParsedConfig(size_t index) const {
70     if (method_configs_ == nullptr) return nullptr;
71     return (*method_configs_)[index].get();
72   }
73 
GetGlobalParsedConfig(size_t index)74   ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) const {
75     if (service_config_ == nullptr) return nullptr;
76     return service_config_->GetGlobalParsedConfig(index);
77   }
78 
SetCallAttribute(CallAttributeInterface * value)79   void SetCallAttribute(CallAttributeInterface* value) {
80     // Overwrite existing entry if we already have one for this type.
81     for (CallAttributeInterface*& attribute : call_attributes_) {
82       if (value->type() == attribute->type()) {
83         attribute = value;
84         return;
85       }
86     }
87     // Otherwise, add a new entry.
88     call_attributes_.EmplaceBack(value);
89   }
90 
GetCallAttribute(UniqueTypeName type)91   CallAttributeInterface* GetCallAttribute(UniqueTypeName type) const {
92     for (CallAttributeInterface* attribute : call_attributes_) {
93       if (attribute->type() == type) return attribute;
94     }
95     return nullptr;
96   }
97 
98  private:
Destroy(void * ptr)99   static void Destroy(void* ptr) {
100     auto* self = static_cast<ServiceConfigCallData*>(ptr);
101     self->~ServiceConfigCallData();
102   }
103 
104   RefCountedPtr<ServiceConfig> service_config_;
105   const ServiceConfigParser::ParsedConfigVector* method_configs_ = nullptr;
106   ChunkedVector<CallAttributeInterface*, 4> call_attributes_;
107 };
108 
109 }  // namespace grpc_core
110 
111 #endif  // GRPC_SRC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H
112