• 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_impl {
30 class ServerContextBase;
31 }  // namespace grpc_impl
32 
33 namespace grpc {
34 
35 namespace internal {
36 class InterceptorBatchMethodsImpl;
37 }
38 
39 namespace experimental {
40 class ServerRpcInfo;
41 
42 // A factory interface for creation of server interceptors. A vector of
43 // factories can be provided to ServerBuilder which will be used to create a new
44 // vector of server interceptors per RPC. Server interceptor authors should
45 // create a subclass of ServerInterceptorFactorInterface which creates objects
46 // of their interceptors.
47 class ServerInterceptorFactoryInterface {
48  public:
~ServerInterceptorFactoryInterface()49   virtual ~ServerInterceptorFactoryInterface() {}
50   // Returns a pointer to an Interceptor object on successful creation, nullptr
51   // otherwise. If nullptr is returned, this server interceptor factory is
52   // ignored for the purposes of that RPC.
53   virtual Interceptor* CreateServerInterceptor(ServerRpcInfo* info) = 0;
54 };
55 
56 /// ServerRpcInfo represents the state of a particular RPC as it
57 /// appears to an interceptor. It is created and owned by the library and
58 /// passed to the CreateServerInterceptor method of the application's
59 /// ServerInterceptorFactoryInterface implementation
60 class ServerRpcInfo {
61  public:
62   /// Type categorizes RPCs by unary or streaming type
63   enum class Type { UNARY, CLIENT_STREAMING, SERVER_STREAMING, BIDI_STREAMING };
64 
~ServerRpcInfo()65   ~ServerRpcInfo() {}
66 
67   // Delete all copy and move constructors and assignments
68   ServerRpcInfo(const ServerRpcInfo&) = delete;
69   ServerRpcInfo& operator=(const ServerRpcInfo&) = delete;
70   ServerRpcInfo(ServerRpcInfo&&) = delete;
71   ServerRpcInfo& operator=(ServerRpcInfo&&) = delete;
72 
73   // Getter methods
74 
75   /// Return the fully-specified method name
method()76   const char* method() const { return method_; }
77 
78   /// Return the type of the RPC (unary or a streaming flavor)
type()79   Type type() const { return type_; }
80 
81   /// Return a pointer to the underlying ServerContext structure associated
82   /// with the RPC to support features that apply to it
server_context()83   grpc_impl::ServerContextBase* server_context() { return ctx_; }
84 
85  private:
86   static_assert(Type::UNARY ==
87                     static_cast<Type>(internal::RpcMethod::NORMAL_RPC),
88                 "violated expectation about Type enum");
89   static_assert(Type::CLIENT_STREAMING ==
90                     static_cast<Type>(internal::RpcMethod::CLIENT_STREAMING),
91                 "violated expectation about Type enum");
92   static_assert(Type::SERVER_STREAMING ==
93                     static_cast<Type>(internal::RpcMethod::SERVER_STREAMING),
94                 "violated expectation about Type enum");
95   static_assert(Type::BIDI_STREAMING ==
96                     static_cast<Type>(internal::RpcMethod::BIDI_STREAMING),
97                 "violated expectation about Type enum");
98 
ServerRpcInfo(grpc_impl::ServerContextBase * ctx,const char * method,internal::RpcMethod::RpcType type)99   ServerRpcInfo(grpc_impl::ServerContextBase* ctx, const char* method,
100                 internal::RpcMethod::RpcType type)
101       : ctx_(ctx), method_(method), type_(static_cast<Type>(type)) {}
102 
103   // Runs interceptor at pos \a pos.
RunInterceptor(experimental::InterceptorBatchMethods * interceptor_methods,size_t pos)104   void RunInterceptor(
105       experimental::InterceptorBatchMethods* interceptor_methods, size_t pos) {
106     GPR_CODEGEN_ASSERT(pos < interceptors_.size());
107     interceptors_[pos]->Intercept(interceptor_methods);
108   }
109 
RegisterInterceptors(const std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> & creators)110   void RegisterInterceptors(
111       const std::vector<
112           std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>&
113           creators) {
114     for (const auto& creator : creators) {
115       auto* interceptor = creator->CreateServerInterceptor(this);
116       if (interceptor != nullptr) {
117         interceptors_.push_back(
118             std::unique_ptr<experimental::Interceptor>(interceptor));
119       }
120     }
121   }
122 
Ref()123   void Ref() { ref_.fetch_add(1, std::memory_order_relaxed); }
Unref()124   void Unref() {
125     if (GPR_UNLIKELY(ref_.fetch_sub(1, std::memory_order_acq_rel) == 1)) {
126       delete this;
127     }
128   }
129 
130   grpc_impl::ServerContextBase* ctx_ = nullptr;
131   const char* method_ = nullptr;
132   const Type type_;
133   std::atomic<intptr_t> ref_{1};
134   std::vector<std::unique_ptr<experimental::Interceptor>> interceptors_;
135 
136   friend class internal::InterceptorBatchMethodsImpl;
137   friend class grpc_impl::ServerContextBase;
138 };
139 
140 }  // namespace experimental
141 }  // namespace grpc
142 
143 #endif  // GRPCPP_IMPL_CODEGEN_SERVER_INTERCEPTOR_H
144