client_interceptor.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //
  2. //
  3. // Copyright 2015 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. #ifndef GRPCPP_SUPPORT_CLIENT_INTERCEPTOR_H
  19. #define GRPCPP_SUPPORT_CLIENT_INTERCEPTOR_H
  20. #include <memory>
  21. #include <vector>
  22. #include <grpc/support/log.h>
  23. #include <grpcpp/impl/rpc_method.h>
  24. #include <grpcpp/support/interceptor.h>
  25. #include <grpcpp/support/string_ref.h>
  26. namespace grpc {
  27. class Channel;
  28. class ClientContext;
  29. namespace internal {
  30. class InterceptorBatchMethodsImpl;
  31. }
  32. namespace experimental {
  33. class ClientRpcInfo;
  34. // A factory interface for creation of client interceptors. A vector of
  35. // factories can be provided at channel creation which will be used to create a
  36. // new vector of client interceptors per RPC. Client interceptor authors should
  37. // create a subclass of ClientInterceptorFactorInterface which creates objects
  38. // of their interceptors.
  39. class ClientInterceptorFactoryInterface {
  40. public:
  41. virtual ~ClientInterceptorFactoryInterface() {}
  42. // Returns a pointer to an Interceptor object on successful creation, nullptr
  43. // otherwise. If nullptr is returned, this server interceptor factory is
  44. // ignored for the purposes of that RPC.
  45. virtual Interceptor* CreateClientInterceptor(ClientRpcInfo* info) = 0;
  46. };
  47. } // namespace experimental
  48. namespace internal {
  49. extern experimental::ClientInterceptorFactoryInterface*
  50. g_global_client_interceptor_factory;
  51. extern experimental::ClientInterceptorFactoryInterface*
  52. g_global_client_stats_interceptor_factory;
  53. } // namespace internal
  54. /// ClientRpcInfo represents the state of a particular RPC as it
  55. /// appears to an interceptor. It is created and owned by the library and
  56. /// passed to the CreateClientInterceptor method of the application's
  57. /// ClientInterceptorFactoryInterface implementation
  58. namespace experimental {
  59. class ClientRpcInfo {
  60. public:
  61. // TODO(yashykt): Stop default-constructing ClientRpcInfo and remove UNKNOWN
  62. // from the list of possible Types.
  63. /// Type categorizes RPCs by unary or streaming type
  64. enum class Type {
  65. UNARY,
  66. CLIENT_STREAMING,
  67. SERVER_STREAMING,
  68. BIDI_STREAMING,
  69. UNKNOWN // UNKNOWN is not API and will be removed later
  70. };
  71. ~ClientRpcInfo() {}
  72. // Delete copy constructor but allow default move constructor
  73. ClientRpcInfo(const ClientRpcInfo&) = delete;
  74. ClientRpcInfo(ClientRpcInfo&&) = default;
  75. // Getter methods
  76. /// Return the fully-specified method name
  77. const char* method() const { return method_; }
  78. /// Return an identifying suffix for the client stub, or nullptr if one wasn't
  79. /// specified.
  80. const char* suffix_for_stats() const { return suffix_for_stats_; }
  81. /// Return a pointer to the channel on which the RPC is being sent
  82. ChannelInterface* channel() { return channel_; }
  83. /// Return a pointer to the underlying ClientContext structure associated
  84. /// with the RPC to support features that apply to it
  85. grpc::ClientContext* client_context() { return ctx_; }
  86. /// Return the type of the RPC (unary or a streaming flavor)
  87. Type type() const { return type_; }
  88. private:
  89. static_assert(Type::UNARY ==
  90. static_cast<Type>(internal::RpcMethod::NORMAL_RPC),
  91. "violated expectation about Type enum");
  92. static_assert(Type::CLIENT_STREAMING ==
  93. static_cast<Type>(internal::RpcMethod::CLIENT_STREAMING),
  94. "violated expectation about Type enum");
  95. static_assert(Type::SERVER_STREAMING ==
  96. static_cast<Type>(internal::RpcMethod::SERVER_STREAMING),
  97. "violated expectation about Type enum");
  98. static_assert(Type::BIDI_STREAMING ==
  99. static_cast<Type>(internal::RpcMethod::BIDI_STREAMING),
  100. "violated expectation about Type enum");
  101. // Default constructor should only be used by ClientContext
  102. ClientRpcInfo() = default;
  103. // Constructor will only be called from ClientContext
  104. ClientRpcInfo(grpc::ClientContext* ctx, internal::RpcMethod::RpcType type,
  105. const char* method, const char* suffix_for_stats,
  106. grpc::ChannelInterface* channel)
  107. : ctx_(ctx),
  108. type_(static_cast<Type>(type)),
  109. method_(method),
  110. suffix_for_stats_(suffix_for_stats),
  111. channel_(channel) {}
  112. // Move assignment should only be used by ClientContext
  113. // TODO(yashykt): Delete move assignment
  114. ClientRpcInfo& operator=(ClientRpcInfo&&) = default;
  115. // Runs interceptor at pos \a pos.
  116. void RunInterceptor(
  117. experimental::InterceptorBatchMethods* interceptor_methods, size_t pos) {
  118. GPR_ASSERT(pos < interceptors_.size());
  119. interceptors_[pos]->Intercept(interceptor_methods);
  120. }
  121. void RegisterInterceptors(
  122. const std::vector<std::unique_ptr<
  123. experimental::ClientInterceptorFactoryInterface>>& creators,
  124. size_t interceptor_pos) {
  125. // TODO(yashykt): This calculation seems broken for the case where an
  126. // interceptor factor returns nullptr.
  127. size_t num_interceptors =
  128. creators.size() +
  129. (internal::g_global_client_stats_interceptor_factory != nullptr) +
  130. (internal::g_global_client_interceptor_factory != nullptr);
  131. if (interceptor_pos > num_interceptors) {
  132. // No interceptors to register
  133. return;
  134. }
  135. if (internal::g_global_client_stats_interceptor_factory != nullptr) {
  136. interceptors_.push_back(std::unique_ptr<experimental::Interceptor>(
  137. internal::g_global_client_stats_interceptor_factory
  138. ->CreateClientInterceptor(this)));
  139. --interceptor_pos;
  140. }
  141. // NOTE: The following is not a range-based for loop because it will only
  142. // iterate over a portion of the creators vector.
  143. for (auto it = creators.begin() + interceptor_pos; it != creators.end();
  144. ++it) {
  145. auto* interceptor = (*it)->CreateClientInterceptor(this);
  146. if (interceptor != nullptr) {
  147. interceptors_.push_back(
  148. std::unique_ptr<experimental::Interceptor>(interceptor));
  149. }
  150. }
  151. if (internal::g_global_client_interceptor_factory != nullptr) {
  152. interceptors_.push_back(std::unique_ptr<experimental::Interceptor>(
  153. internal::g_global_client_interceptor_factory
  154. ->CreateClientInterceptor(this)));
  155. }
  156. }
  157. grpc::ClientContext* ctx_ = nullptr;
  158. // TODO(yashykt): make type_ const once move-assignment is deleted
  159. Type type_{Type::UNKNOWN};
  160. const char* method_ = nullptr;
  161. const char* suffix_for_stats_ = nullptr;
  162. grpc::ChannelInterface* channel_ = nullptr;
  163. std::vector<std::unique_ptr<experimental::Interceptor>> interceptors_;
  164. bool hijacked_ = false;
  165. size_t hijacked_interceptor_ = 0;
  166. friend class internal::InterceptorBatchMethodsImpl;
  167. friend class grpc::ClientContext;
  168. };
  169. // PLEASE DO NOT USE THIS. ALWAYS PREFER PER CHANNEL INTERCEPTORS OVER A GLOBAL
  170. // INTERCEPTOR. IF USAGE IS ABSOLUTELY NECESSARY, PLEASE READ THE SAFETY NOTES.
  171. // Registers a global client interceptor factory object, which is used for all
  172. // RPCs made in this process. The application is responsible for maintaining the
  173. // life of the object while gRPC operations are in progress. The global
  174. // interceptor factory should only be registered once at the start of the
  175. // process before any gRPC operations have begun.
  176. void RegisterGlobalClientInterceptorFactory(
  177. ClientInterceptorFactoryInterface* factory);
  178. // For testing purposes only
  179. void TestOnlyResetGlobalClientInterceptorFactory();
  180. } // namespace experimental
  181. } // namespace grpc
  182. #endif // GRPCPP_SUPPORT_CLIENT_INTERCEPTOR_H