• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_SRC_CORE_FILTER_FILTER_ARGS_H
16 #define GRPC_SRC_CORE_FILTER_FILTER_ARGS_H
17 
18 #include "src/core/filter/blackboard.h"
19 #include "src/core/lib/channel/channel_fwd.h"
20 #include "src/core/util/match.h"
21 
22 namespace grpc_core {
23 
24 // Filter arguments that are independent of channel args.
25 // Here-in should be things that depend on the filters location in the stack, or
26 // things that are ephemeral and disjoint from overall channel args.
27 class FilterArgs {
28  public:
FilterArgs()29   FilterArgs() : FilterArgs(nullptr, nullptr, nullptr) {}
30   FilterArgs(grpc_channel_stack* channel_stack,
31              grpc_channel_element* channel_element,
32              size_t (*channel_stack_filter_instance_number)(
33                  grpc_channel_stack*, grpc_channel_element*),
34              const Blackboard* old_blackboard = nullptr,
35              Blackboard* new_blackboard = nullptr)
impl_(ChannelStackBased{channel_stack, channel_element, channel_stack_filter_instance_number})36       : impl_(ChannelStackBased{channel_stack, channel_element,
37                                 channel_stack_filter_instance_number}),
38         old_blackboard_(old_blackboard),
39         new_blackboard_(new_blackboard) {}
40   // While we're moving to call-v3 we need to have access to
41   // grpc_channel_stack & friends here. That means that we can't rely on this
42   // type signature from interception_chain.h, which means that we need a way
43   // of constructing this object without naming it ===> implicit construction.
44   // TODO(ctiller): remove this once we're fully on call-v3
45   // NOLINTNEXTLINE(google-explicit-constructor)
46   FilterArgs(size_t instance_id, const Blackboard* old_blackboard = nullptr,
47              Blackboard* new_blackboard = nullptr)
impl_(V3Based{instance_id})48       : impl_(V3Based{instance_id}),
49         old_blackboard_(old_blackboard),
50         new_blackboard_(new_blackboard) {}
51 
52   ABSL_DEPRECATED("Direct access to channel stack is deprecated")
channel_stack()53   grpc_channel_stack* channel_stack() const {
54     return absl::get<ChannelStackBased>(impl_).channel_stack;
55   }
56 
57   // Get the instance id of this filter.
58   // This id is unique amongst all filters /of the same type/ and densely
59   // packed (starting at 0) for a given channel stack instantiation.
60   // eg. for a stack with filter types A B C A B D A the instance ids would be
61   // 0 0 0 1 1 0 2.
62   // This is useful for filters that need to store per-instance data in a
63   // parallel data structure.
instance_id()64   size_t instance_id() const {
65     return Match(
66         impl_,
67         [](const ChannelStackBased& cs) {
68           return cs.channel_stack_filter_instance_number(cs.channel_stack,
69                                                          cs.channel_element);
70         },
71         [](const V3Based& v3) { return v3.instance_id; });
72   }
73 
74   // If a filter state object of type T exists for key from a previous
75   // filter stack, retains it for the new filter stack we're constructing.
76   // Otherwise, invokes create_func() to create a new filter state
77   // object for the new filter stack.  Returns the new filter state object.
78   template <typename T>
GetOrCreateState(const std::string & key,absl::FunctionRef<RefCountedPtr<T> ()> create_func)79   RefCountedPtr<T> GetOrCreateState(
80       const std::string& key,
81       absl::FunctionRef<RefCountedPtr<T>()> create_func) {
82     RefCountedPtr<T> state;
83     if (old_blackboard_ != nullptr) state = old_blackboard_->Get<T>(key);
84     if (state == nullptr) state = create_func();
85     if (new_blackboard_ != nullptr) new_blackboard_->Set(key, state);
86     return state;
87   }
88 
89  private:
90   friend class ChannelFilter;
91 
92   struct ChannelStackBased {
93     grpc_channel_stack* channel_stack;
94     grpc_channel_element* channel_element;
95     size_t (*channel_stack_filter_instance_number)(grpc_channel_stack*,
96                                                    grpc_channel_element*);
97   };
98 
99   struct V3Based {
100     size_t instance_id;
101   };
102 
103   using Impl = absl::variant<ChannelStackBased, V3Based>;
104   Impl impl_;
105 
106   const Blackboard* old_blackboard_ = nullptr;
107   Blackboard* new_blackboard_ = nullptr;
108 };
109 
110 }  // namespace grpc_core
111 
112 #endif  // GRPC_SRC_CORE_FILTER_FILTER_ARGS_H
113