GRPC C++  1.17.0
interceptor_common.h
Go to the documentation of this file.
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_INTERCEPTOR_COMMON_H
20 #define GRPCPP_IMPL_CODEGEN_INTERCEPTOR_COMMON_H
21 
22 #include <array>
23 #include <functional>
24 
30 
32 
33 namespace grpc {
34 namespace internal {
35 
38  public:
40  for (auto i = static_cast<experimental::InterceptionHookPoints>(0);
42  i = static_cast<experimental::InterceptionHookPoints>(
43  static_cast<size_t>(i) + 1)) {
44  hooks_[static_cast<size_t>(i)] = false;
45  }
46  }
47 
49 
52  return hooks_[static_cast<size_t>(type)];
53  }
54 
55  void Proceed() override {
56  if (call_->client_rpc_info() != nullptr) {
57  return ProceedClient();
58  }
59  GPR_CODEGEN_ASSERT(call_->server_rpc_info() != nullptr);
60  ProceedServer();
61  }
62 
63  void Hijack() override {
64  // Only the client can hijack when sending down initial metadata
65  GPR_CODEGEN_ASSERT(!reverse_ && ops_ != nullptr &&
66  call_->client_rpc_info() != nullptr);
67  // It is illegal to call Hijack twice
68  GPR_CODEGEN_ASSERT(!ran_hijacking_interceptor_);
69  auto* rpc_info = call_->client_rpc_info();
70  rpc_info->hijacked_ = true;
71  rpc_info->hijacked_interceptor_ = current_interceptor_index_;
72  ClearHookPoints();
73  ops_->SetHijackingState();
74  ran_hijacking_interceptor_ = true;
75  rpc_info->RunInterceptor(this, current_interceptor_index_);
76  }
77 
79  hooks_[static_cast<size_t>(type)] = true;
80  }
81 
82  ByteBuffer* GetSendMessage() override { return send_message_; }
83 
84  std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
85  return send_initial_metadata_;
86  }
87 
88  Status GetSendStatus() override {
89  return Status(static_cast<StatusCode>(*code_), *error_message_,
90  *error_details_);
91  }
92 
93  void ModifySendStatus(const Status& status) override {
94  *code_ = static_cast<grpc_status_code>(status.error_code());
95  *error_details_ = status.error_details();
96  *error_message_ = status.error_message();
97  }
98 
99  std::multimap<grpc::string, grpc::string>* GetSendTrailingMetadata()
100  override {
101  return send_trailing_metadata_;
102  }
103 
104  void* GetRecvMessage() override { return recv_message_; }
105 
106  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvInitialMetadata()
107  override {
108  return recv_initial_metadata_->map();
109  }
110 
111  Status* GetRecvStatus() override { return recv_status_; }
112 
113  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvTrailingMetadata()
114  override {
115  return recv_trailing_metadata_->map();
116  }
117 
118  void SetSendMessage(ByteBuffer* buf) { send_message_ = buf; }
119 
121  std::multimap<grpc::string, grpc::string>* metadata) {
122  send_initial_metadata_ = metadata;
123  }
124 
125  void SetSendStatus(grpc_status_code* code, grpc::string* error_details,
126  grpc::string* error_message) {
127  code_ = code;
128  error_details_ = error_details;
129  error_message_ = error_message;
130  }
131 
133  std::multimap<grpc::string, grpc::string>* metadata) {
134  send_trailing_metadata_ = metadata;
135  }
136 
137  void SetRecvMessage(void* message) { recv_message_ = message; }
138 
140  recv_initial_metadata_ = map;
141  }
142 
143  void SetRecvStatus(Status* status) { recv_status_ = status; }
144 
146  recv_trailing_metadata_ = map;
147  }
148 
149  std::unique_ptr<ChannelInterface> GetInterceptedChannel() override {
150  auto* info = call_->client_rpc_info();
151  if (info == nullptr) {
152  return std::unique_ptr<ChannelInterface>(nullptr);
153  }
154  // The intercepted channel starts from the interceptor just after the
155  // current interceptor
156  return std::unique_ptr<ChannelInterface>(new InterceptedChannel(
157  info->channel(), current_interceptor_index_ + 1));
158  }
159 
160  // Clears all state
161  void ClearState() {
162  reverse_ = false;
163  ran_hijacking_interceptor_ = false;
164  ClearHookPoints();
165  }
166 
167  // Prepares for Post_recv operations
168  void SetReverse() {
169  reverse_ = true;
170  ran_hijacking_interceptor_ = false;
171  ClearHookPoints();
172  }
173 
174  // This needs to be set before interceptors are run
175  void SetCall(Call* call) { call_ = call; }
176 
177  // This needs to be set before interceptors are run using RunInterceptors().
178  // Alternatively, RunInterceptors(std::function<void(void)> f) can be used.
179  void SetCallOpSetInterface(CallOpSetInterface* ops) { ops_ = ops; }
180 
181  // Returns true if no interceptors are run. This should be used only by
182  // subclasses of CallOpSetInterface. SetCall and SetCallOpSetInterface should
183  // have been called before this. After all the interceptors are done running,
184  // either ContinueFillOpsAfterInterception or
185  // ContinueFinalizeOpsAfterInterception will be called. Note that neither of
186  // them is invoked if there were no interceptors registered.
188  GPR_CODEGEN_ASSERT(ops_);
189  auto* client_rpc_info = call_->client_rpc_info();
190  if (client_rpc_info != nullptr) {
191  if (client_rpc_info->interceptors_.size() == 0) {
192  return true;
193  } else {
194  RunClientInterceptors();
195  return false;
196  }
197  }
198 
199  auto* server_rpc_info = call_->server_rpc_info();
200  if (server_rpc_info == nullptr ||
201  server_rpc_info->interceptors_.size() == 0) {
202  return true;
203  }
204  RunServerInterceptors();
205  return false;
206  }
207 
208  // Returns true if no interceptors are run. Returns false otherwise if there
209  // are interceptors registered. After the interceptors are done running \a f
210  // will be invoked. This is to be used only by BaseAsyncRequest and
211  // SyncRequest.
212  bool RunInterceptors(std::function<void(void)> f) {
213  // This is used only by the server for initial call request
214  GPR_CODEGEN_ASSERT(reverse_ == true);
215  GPR_CODEGEN_ASSERT(call_->client_rpc_info() == nullptr);
216  auto* server_rpc_info = call_->server_rpc_info();
217  if (server_rpc_info == nullptr ||
218  server_rpc_info->interceptors_.size() == 0) {
219  return true;
220  }
221  callback_ = std::move(f);
222  RunServerInterceptors();
223  return false;
224  }
225 
226  private:
227  void RunClientInterceptors() {
228  auto* rpc_info = call_->client_rpc_info();
229  if (!reverse_) {
230  current_interceptor_index_ = 0;
231  } else {
232  if (rpc_info->hijacked_) {
233  current_interceptor_index_ = rpc_info->hijacked_interceptor_;
234  } else {
235  current_interceptor_index_ = rpc_info->interceptors_.size() - 1;
236  }
237  }
238  rpc_info->RunInterceptor(this, current_interceptor_index_);
239  }
240 
241  void RunServerInterceptors() {
242  auto* rpc_info = call_->server_rpc_info();
243  if (!reverse_) {
244  current_interceptor_index_ = 0;
245  } else {
246  current_interceptor_index_ = rpc_info->interceptors_.size() - 1;
247  }
248  rpc_info->RunInterceptor(this, current_interceptor_index_);
249  }
250 
251  void ProceedClient() {
252  auto* rpc_info = call_->client_rpc_info();
253  if (rpc_info->hijacked_ && !reverse_ &&
254  current_interceptor_index_ == rpc_info->hijacked_interceptor_ &&
255  !ran_hijacking_interceptor_) {
256  // We now need to provide hijacked recv ops to this interceptor
257  ClearHookPoints();
258  ops_->SetHijackingState();
259  ran_hijacking_interceptor_ = true;
260  rpc_info->RunInterceptor(this, current_interceptor_index_);
261  return;
262  }
263  if (!reverse_) {
264  current_interceptor_index_++;
265  // We are going down the stack of interceptors
266  if (current_interceptor_index_ < rpc_info->interceptors_.size()) {
267  if (rpc_info->hijacked_ &&
268  current_interceptor_index_ > rpc_info->hijacked_interceptor_) {
269  // This is a hijacked RPC and we are done with hijacking
271  } else {
272  rpc_info->RunInterceptor(this, current_interceptor_index_);
273  }
274  } else {
275  // we are done running all the interceptors without any hijacking
277  }
278  } else {
279  // We are going up the stack of interceptors
280  if (current_interceptor_index_ > 0) {
281  // Continue running interceptors
282  current_interceptor_index_--;
283  rpc_info->RunInterceptor(this, current_interceptor_index_);
284  } else {
285  // we are done running all the interceptors without any hijacking
287  }
288  }
289  }
290 
291  void ProceedServer() {
292  auto* rpc_info = call_->server_rpc_info();
293  if (!reverse_) {
294  current_interceptor_index_++;
295  if (current_interceptor_index_ < rpc_info->interceptors_.size()) {
296  return rpc_info->RunInterceptor(this, current_interceptor_index_);
297  } else if (ops_) {
298  return ops_->ContinueFillOpsAfterInterception();
299  }
300  } else {
301  // We are going up the stack of interceptors
302  if (current_interceptor_index_ > 0) {
303  // Continue running interceptors
304  current_interceptor_index_--;
305  return rpc_info->RunInterceptor(this, current_interceptor_index_);
306  } else if (ops_) {
308  }
309  }
310  GPR_CODEGEN_ASSERT(callback_);
311  callback_();
312  }
313 
314  void ClearHookPoints() {
315  for (auto i = static_cast<experimental::InterceptionHookPoints>(0);
317  i = static_cast<experimental::InterceptionHookPoints>(
318  static_cast<size_t>(i) + 1)) {
319  hooks_[static_cast<size_t>(i)] = false;
320  }
321  }
322 
323  std::array<bool,
324  static_cast<size_t>(
326  hooks_;
327 
328  size_t current_interceptor_index_ = 0; // Current iterator
329  bool reverse_ = false;
330  bool ran_hijacking_interceptor_ = false;
331  Call* call_ = nullptr; // The Call object is present along with CallOpSet
332  // object/callback
333  CallOpSetInterface* ops_ = nullptr;
334  std::function<void(void)> callback_;
335 
336  ByteBuffer* send_message_ = nullptr;
337 
338  std::multimap<grpc::string, grpc::string>* send_initial_metadata_;
339 
340  grpc_status_code* code_ = nullptr;
341  grpc::string* error_details_ = nullptr;
342  grpc::string* error_message_ = nullptr;
343  Status send_status_;
344 
345  std::multimap<grpc::string, grpc::string>* send_trailing_metadata_ = nullptr;
346 
347  void* recv_message_ = nullptr;
348 
349  MetadataMap* recv_initial_metadata_ = nullptr;
350 
351  Status* recv_status_ = nullptr;
352 
353  MetadataMap* recv_trailing_metadata_ = nullptr;
354 };
355 
356 // A special implementation of InterceptorBatchMethods to send a Cancel
357 // notification down the interceptor stack
360  public:
362  experimental::InterceptionHookPoints type) override {
364  return true;
365  } else {
366  return false;
367  }
368  }
369 
370  void Proceed() override {
371  // This is a no-op. For actual continuation of the RPC simply needs to
372  // return from the Intercept method
373  }
374 
375  void Hijack() override {
376  // Only the client can hijack when sending down initial metadata
377  GPR_CODEGEN_ASSERT(false &&
378  "It is illegal to call Hijack on a method which has a "
379  "Cancel notification");
380  }
381 
383  GPR_CODEGEN_ASSERT(false &&
384  "It is illegal to call GetSendMessage on a method which "
385  "has a Cancel notification");
386  return nullptr;
387  }
388 
389  std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
390  GPR_CODEGEN_ASSERT(false &&
391  "It is illegal to call GetSendInitialMetadata on a "
392  "method which has a Cancel notification");
393  return nullptr;
394  }
395 
396  Status GetSendStatus() override {
397  GPR_CODEGEN_ASSERT(false &&
398  "It is illegal to call GetSendStatus on a method which "
399  "has a Cancel notification");
400  return Status();
401  }
402 
403  void ModifySendStatus(const Status& status) override {
404  GPR_CODEGEN_ASSERT(false &&
405  "It is illegal to call ModifySendStatus on a method "
406  "which has a Cancel notification");
407  return;
408  }
409 
410  std::multimap<grpc::string, grpc::string>* GetSendTrailingMetadata()
411  override {
412  GPR_CODEGEN_ASSERT(false &&
413  "It is illegal to call GetSendTrailingMetadata on a "
414  "method which has a Cancel notification");
415  return nullptr;
416  }
417 
418  void* GetRecvMessage() override {
419  GPR_CODEGEN_ASSERT(false &&
420  "It is illegal to call GetRecvMessage on a method which "
421  "has a Cancel notification");
422  return nullptr;
423  }
424 
425  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvInitialMetadata()
426  override {
427  GPR_CODEGEN_ASSERT(false &&
428  "It is illegal to call GetRecvInitialMetadata on a "
429  "method which has a Cancel notification");
430  return nullptr;
431  }
432 
433  Status* GetRecvStatus() override {
434  GPR_CODEGEN_ASSERT(false &&
435  "It is illegal to call GetRecvStatus on a method which "
436  "has a Cancel notification");
437  return nullptr;
438  }
439 
440  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvTrailingMetadata()
441  override {
442  GPR_CODEGEN_ASSERT(false &&
443  "It is illegal to call GetRecvTrailingMetadata on a "
444  "method which has a Cancel notification");
445  return nullptr;
446  }
447 
448  std::unique_ptr<ChannelInterface> GetInterceptedChannel() override {
449  GPR_CODEGEN_ASSERT(false &&
450  "It is illegal to call GetInterceptedChannel on a "
451  "method which has a Cancel notification");
452  return std::unique_ptr<ChannelInterface>(nullptr);
453  }
454 };
455 } // namespace internal
456 } // namespace grpc
457 
458 #endif // GRPCPP_IMPL_CODEGEN_INTERCEPTOR_COMMON_H
bool RunInterceptors(std::function< void(void)> f)
Definition: interceptor_common.h:212
void SetRecvMessage(void *message)
Definition: interceptor_common.h:137
std::multimap< grpc::string_ref, grpc::string_ref > * GetRecvInitialMetadata() override
Definition: interceptor_common.h:425
void SetCall(Call *call)
Definition: interceptor_common.h:175
grpc_status_code
Definition: status.h:26
void ModifySendStatus(const Status &status) override
Definition: interceptor_common.h:93
#define GPR_CODEGEN_ASSERT(x)
Codegen specific version of GPR_ASSERT.
Definition: core_codegen_interface.h:141
Definition: interceptor_common.h:358
std::string string
Definition: config.h:35
Status * GetRecvStatus() override
Definition: interceptor_common.h:111
void SetSendMessage(ByteBuffer *buf)
Definition: interceptor_common.h:118
std::multimap< grpc::string, grpc::string > * GetSendInitialMetadata() override
Definition: interceptor_common.h:389
Definition: metadata_map.h:33
std::multimap< grpc::string_ref, grpc::string_ref > * GetRecvTrailingMetadata() override
Definition: interceptor_common.h:440
void * GetRecvMessage() override
Definition: interceptor_common.h:418
std::multimap< grpc::string_ref, grpc::string_ref > * GetRecvInitialMetadata() override
Definition: interceptor_common.h:106
void SetReverse()
Definition: interceptor_common.h:168
void SetRecvStatus(Status *status)
Definition: interceptor_common.h:143
InterceptorBatchMethodsImpl()
Definition: interceptor_common.h:39
std::unique_ptr< ChannelInterface > GetInterceptedChannel() override
Definition: interceptor_common.h:448
std::multimap< grpc::string_ref, grpc::string_ref > * GetRecvTrailingMetadata() override
Definition: interceptor_common.h:113
void ModifySendStatus(const Status &status) override
Definition: interceptor_common.h:403
bool QueryInterceptionHookPoint(experimental::InterceptionHookPoints type) override
Definition: interceptor_common.h:50
virtual void ContinueFillOpsAfterInterception()=0
void Hijack() override
Definition: interceptor_common.h:63
ByteBuffer * GetSendMessage() override
Definition: interceptor_common.h:382
bool RunInterceptors()
Definition: interceptor_common.h:187
Status GetSendStatus() override
Definition: interceptor_common.h:396
::google::protobuf::util::Status Status
Definition: config_protobuf.h:93
InterceptionHookPoints
Definition: interceptor.h:43
Status * GetRecvStatus() override
Definition: interceptor_common.h:433
grpc::string error_message() const
Return the instance&#39;s error message.
Definition: status.h:112
ByteBuffer * GetSendMessage() override
Definition: interceptor_common.h:82
StatusCode error_code() const
Return the instance&#39;s error code.
Definition: status.h:110
void Proceed() override
Definition: interceptor_common.h:370
An InterceptedChannel is available to client Interceptors.
Definition: intercepted_channel.h:34
virtual void ContinueFinalizeResultAfterInterception()=0
std::multimap< grpc::string_ref, grpc::string_ref > * map()
Definition: metadata_map.h:66
void * GetRecvMessage() override
Definition: interceptor_common.h:104
experimental::ServerRpcInfo * server_rpc_info() const
Definition: call.h:79
An Alarm posts the user provided tag to its associated completion queue upon expiry or cancellation...
Definition: alarm.h:33
std::multimap< grpc::string, grpc::string > * GetSendTrailingMetadata() override
Definition: interceptor_common.h:99
Definition: interceptor_common.h:36
Status GetSendStatus() override
Definition: interceptor_common.h:88
experimental::ClientRpcInfo * client_rpc_info() const
Definition: call.h:75
std::multimap< grpc::string, grpc::string > * GetSendInitialMetadata() override
Definition: interceptor_common.h:84
~InterceptorBatchMethodsImpl()
Definition: interceptor_common.h:48
bool QueryInterceptionHookPoint(experimental::InterceptionHookPoints type) override
Definition: interceptor_common.h:361
An abstract collection of call ops, used to generate the grpc_call_op structure to pass down to the l...
Definition: call_op_set_interface.h:34
void SetSendStatus(grpc_status_code *code, grpc::string *error_details, grpc::string *error_message)
Definition: interceptor_common.h:125
void SetSendTrailingMetadata(std::multimap< grpc::string, grpc::string > *metadata)
Definition: interceptor_common.h:132
void SetRecvInitialMetadata(MetadataMap *map)
Definition: interceptor_common.h:139
void ClearState()
Definition: interceptor_common.h:161
void Hijack() override
Definition: interceptor_common.h:375
std::multimap< grpc::string, grpc::string > * GetSendTrailingMetadata() override
Definition: interceptor_common.h:410
void SetSendInitialMetadata(std::multimap< grpc::string, grpc::string > *metadata)
Definition: interceptor_common.h:120
Did it work? If it didn&#39;t, why?
Definition: status.h:31
void Proceed() override
Definition: interceptor_common.h:55
void AddInterceptionHookPoint(experimental::InterceptionHookPoints type)
Definition: interceptor_common.h:78
std::unique_ptr< ChannelInterface > GetInterceptedChannel() override
Definition: interceptor_common.h:149
void SetRecvTrailingMetadata(MetadataMap *map)
Definition: interceptor_common.h:145
void SetCallOpSetInterface(CallOpSetInterface *ops)
Definition: interceptor_common.h:179
A sequence of bytes.
Definition: byte_buffer.h:62
grpc::string error_details() const
Return the (binary) error details.
Definition: status.h:115
Straightforward wrapping of the C call object.
Definition: call.h:36