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