• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPCPP_IMPL_CODEGEN_SERVER_INTERCEPTOR_H
20 #define GRPCPP_IMPL_CODEGEN_SERVER_INTERCEPTOR_H
21 
22 #include <atomic>
23 #include <vector>
24 
25 #include <grpcpp/impl/codegen/interceptor.h>
26 #include <grpcpp/impl/codegen/rpc_method.h>
27 #include <grpcpp/impl/codegen/string_ref.h>
28 
29 namespace grpc {
30 class ServerContextBase;
31 namespace internal {
32 class InterceptorBatchMethodsImpl;
33 }
34 
35 namespace experimental {
36 class ServerRpcInfo;
37 
38 // A factory interface for creation of server interceptors. A vector of
39 // factories can be provided to ServerBuilder which will be used to create a new
40 // vector of server interceptors per RPC. Server interceptor authors should
41 // create a subclass of ServerInterceptorFactorInterface which creates objects
42 // of their interceptors.
43 class ServerInterceptorFactoryInterface {
44  public:
~ServerInterceptorFactoryInterface()45   virtual ~ServerInterceptorFactoryInterface() {}
46   // Returns a pointer to an Interceptor object on successful creation, nullptr
47   // otherwise. If nullptr is returned, this server interceptor factory is
48   // ignored for the purposes of that RPC.
49   virtual Interceptor* CreateServerInterceptor(ServerRpcInfo* info) = 0;
50 };
51 
52 /// ServerRpcInfo represents the state of a particular RPC as it
53 /// appears to an interceptor. It is created and owned by the library and
54 /// passed to the CreateServerInterceptor method of the application's
55 /// ServerInterceptorFactoryInterface implementation
56 class ServerRpcInfo {
57  public:
58   /// Type categorizes RPCs by unary or streaming type
59   enum class Type { UNARY, CLIENT_STREAMING, SERVER_STREAMING, BIDI_STREAMING };
60 
~ServerRpcInfo()61   ~ServerRpcInfo() {}
62 
63   // Delete all copy and move constructors and assignments
64   ServerRpcInfo(const ServerRpcInfo&) = delete;
65   ServerRpcInfo& operator=(const ServerRpcInfo&) = delete;
66   ServerRpcInfo(ServerRpcInfo&&) = delete;
67   ServerRpcInfo& operator=(ServerRpcInfo&&) = delete;
68 
69   // Getter methods
70 
71   /// Return the fully-specified method name
method()72   const char* method() const { return method_; }
73 
74   /// Return the type of the RPC (unary or a streaming flavor)
type()75   Type type() const { return type_; }
76 
77   /// Return a pointer to the underlying ServerContext structure associated
78   /// with the RPC to support features that apply to it
server_context()79   ServerContextBase* server_context() { return ctx_; }
80 
81  private:
82   static_assert(Type::UNARY ==
83                     static_cast<Type>(internal::RpcMethod::NORMAL_RPC),
84                 "violated expectation about Type enum");
85   static_assert(Type::CLIENT_STREAMING ==
86                     static_cast<Type>(internal::RpcMethod::CLIENT_STREAMING),
87                 "violated expectation about Type enum");
88   static_assert(Type::SERVER_STREAMING ==
89                     static_cast<Type>(internal::RpcMethod::SERVER_STREAMING),
90                 "violated expectation about Type enum");
91   static_assert(Type::BIDI_STREAMING ==
92                     static_cast<Type>(internal::RpcMethod::BIDI_STREAMING),
93                 "violated expectation about Type enum");
94 
ServerRpcInfo(ServerContextBase * ctx,const char * method,internal::RpcMethod::RpcType type)95   ServerRpcInfo(ServerContextBase* ctx, const char* method,
96                 internal::RpcMethod::RpcType type)
97       : ctx_(ctx), method_(method), type_(static_cast<Type>(type)) {}
98 
99   // Runs interceptor at pos \a pos.
RunInterceptor(experimental::InterceptorBatchMethods * interceptor_methods,size_t pos)100   void RunInterceptor(
101       experimental::InterceptorBatchMethods* interceptor_methods, size_t pos) {
102     GPR_CODEGEN_ASSERT(pos < interceptors_.size());
103     interceptors_[pos]->Intercept(interceptor_methods);
104   }
105 
RegisterInterceptors(const std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> & creators)106   void RegisterInterceptors(
107       const std::vector<
108           std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>&
109           creators) {
110     for (const auto& creator : creators) {
111       auto* interceptor = creator->CreateServerInterceptor(this);
112       if (interceptor != nullptr) {
113         interceptors_.push_back(
114             std::unique_ptr<experimental::Interceptor>(interceptor));
115       }
116     }
117   }
118 
Ref()119   void Ref() { ref_.fetch_add(1, std::memory_order_relaxed); }
Unref()120   void Unref() {
121     if (GPR_UNLIKELY(ref_.fetch_sub(1, std::memory_order_acq_rel) == 1)) {
122       delete this;
123     }
124   }
125 
126   ServerContextBase* ctx_ = nullptr;
127   const char* method_ = nullptr;
128   const Type type_;
129   std::atomic<intptr_t> ref_{1};
130   std::vector<std::unique_ptr<experimental::Interceptor>> interceptors_;
131 
132   friend class internal::InterceptorBatchMethodsImpl;
133   friend class grpc::ServerContextBase;
134 };
135 
136 }  // namespace experimental
137 }  // namespace grpc
138 
139 #endif  // GRPCPP_IMPL_CODEGEN_SERVER_INTERCEPTOR_H
140