GRPC C++  0.12.0.0
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
call.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015, Google Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #ifndef GRPCXX_IMPL_CALL_H
35 #define GRPCXX_IMPL_CALL_H
36 
37 #include <functional>
38 #include <memory>
39 #include <map>
40 #include <cstring>
41 
42 #include <grpc/support/alloc.h>
43 #include <grpc++/client_context.h>
46 #include <grpc++/support/config.h>
47 #include <grpc++/support/status.h>
48 
49 struct grpc_call;
50 struct grpc_op;
51 
52 namespace grpc {
53 
54 class ByteBuffer;
55 class Call;
56 
57 void FillMetadataMap(
58  grpc_metadata_array* arr,
59  std::multimap<grpc::string_ref, grpc::string_ref>* metadata);
60 grpc_metadata* FillMetadataArray(
61  const std::multimap<grpc::string, grpc::string>& metadata);
62 
64 class WriteOptions {
65  public:
66  WriteOptions() : flags_(0) {}
67  WriteOptions(const WriteOptions& other) : flags_(other.flags_) {}
68 
70  inline void Clear() { flags_ = 0; }
71 
73  inline gpr_uint32 flags() const { return flags_; }
74 
79  SetBit(GRPC_WRITE_NO_COMPRESS);
80  return *this;
81  }
82 
87  ClearBit(GRPC_WRITE_NO_COMPRESS);
88  return *this;
89  }
90 
95  inline bool get_no_compression() const {
96  return GetBit(GRPC_WRITE_NO_COMPRESS);
97  }
98 
104  SetBit(GRPC_WRITE_BUFFER_HINT);
105  return *this;
106  }
107 
113  ClearBit(GRPC_WRITE_BUFFER_HINT);
114  return *this;
115  }
116 
121  inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
122 
124  flags_ = rhs.flags_;
125  return *this;
126  }
127 
128  private:
129  void SetBit(const gpr_uint32 mask) { flags_ |= mask; }
130 
131  void ClearBit(const gpr_uint32 mask) { flags_ &= ~mask; }
132 
133  bool GetBit(const gpr_uint32 mask) const { return (flags_ & mask) != 0; }
134 
135  gpr_uint32 flags_;
136 };
137 
140 template <int I>
141 class CallNoOp {
142  protected:
143  void AddOp(grpc_op* ops, size_t* nops) {}
144  void FinishOp(bool* status, int max_message_size) {}
145 };
146 
148  public:
150 
152  const std::multimap<grpc::string, grpc::string>& metadata) {
153  send_ = true;
154  initial_metadata_count_ = metadata.size();
156  }
157 
158  protected:
159  void AddOp(grpc_op* ops, size_t* nops) {
160  if (!send_) return;
161  grpc_op* op = &ops[(*nops)++];
162  op->op = GRPC_OP_SEND_INITIAL_METADATA;
163  op->flags = 0;
164  op->reserved = NULL;
165  op->data.send_initial_metadata.count = initial_metadata_count_;
166  op->data.send_initial_metadata.metadata = initial_metadata_;
167  }
168  void FinishOp(bool* status, int max_message_size) {
169  if (!send_) return;
170  gpr_free(initial_metadata_);
171  send_ = false;
172  }
173 
174  bool send_;
176  grpc_metadata* initial_metadata_;
177 };
178 
180  public:
181  CallOpSendMessage() : send_buf_(nullptr), own_buf_(false) {}
182 
185  template <class M>
186  Status SendMessage(const M& message,
187  const WriteOptions& options) GRPC_MUST_USE_RESULT;
188 
189  template <class M>
190  Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
191 
192  protected:
193  void AddOp(grpc_op* ops, size_t* nops) {
194  if (send_buf_ == nullptr) return;
195  grpc_op* op = &ops[(*nops)++];
196  op->op = GRPC_OP_SEND_MESSAGE;
197  op->flags = write_options_.flags();
198  op->reserved = NULL;
199  op->data.send_message = send_buf_;
200  // Flags are per-message: clear them after use.
201  write_options_.Clear();
202  }
203  void FinishOp(bool* status, int max_message_size) {
204  if (own_buf_) grpc_byte_buffer_destroy(send_buf_);
205  send_buf_ = nullptr;
206  }
207 
208  private:
209  grpc_byte_buffer* send_buf_;
210  WriteOptions write_options_;
211  bool own_buf_;
212 };
213 
214 template <class M>
216  const WriteOptions& options) {
217  write_options_ = options;
218  return SerializationTraits<M>::Serialize(message, &send_buf_, &own_buf_);
219 }
220 
221 template <class M>
223  return SendMessage(message, WriteOptions());
224 }
225 
226 template <class R>
228  public:
229  CallOpRecvMessage() : got_message(false), message_(nullptr) {}
230 
231  void RecvMessage(R* message) { message_ = message; }
232 
234 
235  protected:
236  void AddOp(grpc_op* ops, size_t* nops) {
237  if (message_ == nullptr) return;
238  grpc_op* op = &ops[(*nops)++];
239  op->op = GRPC_OP_RECV_MESSAGE;
240  op->flags = 0;
241  op->reserved = NULL;
242  op->data.recv_message = &recv_buf_;
243  }
244 
245  void FinishOp(bool* status, int max_message_size) {
246  if (message_ == nullptr) return;
247  if (recv_buf_) {
248  if (*status) {
249  got_message = true;
250  *status = SerializationTraits<R>::Deserialize(recv_buf_, message_,
251  max_message_size).ok();
252  } else {
253  got_message = false;
254  grpc_byte_buffer_destroy(recv_buf_);
255  }
256  } else {
257  got_message = false;
258  *status = false;
259  }
260  message_ = nullptr;
261  }
262 
263  private:
264  R* message_;
265  grpc_byte_buffer* recv_buf_;
266 };
267 
268 namespace CallOpGenericRecvMessageHelper {
270  public:
271  virtual Status Deserialize(grpc_byte_buffer* buf, int max_message_size) = 0;
272 };
273 
274 template <class R>
276  public:
277  DeserializeFuncType(R* message) : message_(message) {}
278  Status Deserialize(grpc_byte_buffer* buf,
279  int max_message_size) GRPC_OVERRIDE {
280  return SerializationTraits<R>::Deserialize(buf, message_, max_message_size);
281  }
282 
283  private:
284  R* message_; // Not a managed pointer because management is external to this
285 };
286 } // namespace CallOpGenericRecvMessageHelper
287 
289  public:
291 
292  template <class R>
293  void RecvMessage(R* message) {
294  deserialize_.reset(
296  }
297 
299 
300  protected:
301  void AddOp(grpc_op* ops, size_t* nops) {
302  if (!deserialize_) return;
303  grpc_op* op = &ops[(*nops)++];
304  op->op = GRPC_OP_RECV_MESSAGE;
305  op->flags = 0;
306  op->reserved = NULL;
307  op->data.recv_message = &recv_buf_;
308  }
309 
310  void FinishOp(bool* status, int max_message_size) {
311  if (!deserialize_) return;
312  if (recv_buf_) {
313  if (*status) {
314  got_message = true;
315  *status = deserialize_->Deserialize(recv_buf_, max_message_size).ok();
316  } else {
317  got_message = false;
318  grpc_byte_buffer_destroy(recv_buf_);
319  }
320  } else {
321  got_message = false;
322  *status = false;
323  }
324  deserialize_.reset();
325  }
326 
327  private:
328  std::unique_ptr<CallOpGenericRecvMessageHelper::DeserializeFunc> deserialize_;
329  grpc_byte_buffer* recv_buf_;
330 };
331 
333  public:
334  CallOpClientSendClose() : send_(false) {}
335 
336  void ClientSendClose() { send_ = true; }
337 
338  protected:
339  void AddOp(grpc_op* ops, size_t* nops) {
340  if (!send_) return;
341  grpc_op* op = &ops[(*nops)++];
342  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
343  op->flags = 0;
344  op->reserved = NULL;
345  }
346  void FinishOp(bool* status, int max_message_size) { send_ = false; }
347 
348  private:
349  bool send_;
350 };
351 
353  public:
354  CallOpServerSendStatus() : send_status_available_(false) {}
355 
357  const std::multimap<grpc::string, grpc::string>& trailing_metadata,
358  const Status& status) {
359  trailing_metadata_count_ = trailing_metadata.size();
360  trailing_metadata_ = FillMetadataArray(trailing_metadata);
361  send_status_available_ = true;
362  send_status_code_ = static_cast<grpc_status_code>(status.error_code());
363  send_status_details_ = status.error_message();
364  }
365 
366  protected:
367  void AddOp(grpc_op* ops, size_t* nops) {
368  if (!send_status_available_) return;
369  grpc_op* op = &ops[(*nops)++];
370  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
371  op->data.send_status_from_server.trailing_metadata_count =
372  trailing_metadata_count_;
373  op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
374  op->data.send_status_from_server.status = send_status_code_;
375  op->data.send_status_from_server.status_details =
376  send_status_details_.empty() ? nullptr : send_status_details_.c_str();
377  op->flags = 0;
378  op->reserved = NULL;
379  }
380 
381  void FinishOp(bool* status, int max_message_size) {
382  if (!send_status_available_) return;
383  gpr_free(trailing_metadata_);
384  send_status_available_ = false;
385  }
386 
387  private:
388  bool send_status_available_;
389  grpc_status_code send_status_code_;
390  grpc::string send_status_details_;
391  size_t trailing_metadata_count_;
392  grpc_metadata* trailing_metadata_;
393 };
394 
396  public:
397  CallOpRecvInitialMetadata() : recv_initial_metadata_(nullptr) {}
398 
400  context->initial_metadata_received_ = true;
401  recv_initial_metadata_ = &context->recv_initial_metadata_;
402  }
403 
404  protected:
405  void AddOp(grpc_op* ops, size_t* nops) {
406  if (!recv_initial_metadata_) return;
407  memset(&recv_initial_metadata_arr_, 0, sizeof(recv_initial_metadata_arr_));
408  grpc_op* op = &ops[(*nops)++];
409  op->op = GRPC_OP_RECV_INITIAL_METADATA;
410  op->data.recv_initial_metadata = &recv_initial_metadata_arr_;
411  op->flags = 0;
412  op->reserved = NULL;
413  }
414  void FinishOp(bool* status, int max_message_size) {
415  if (recv_initial_metadata_ == nullptr) return;
416  FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
417  recv_initial_metadata_ = nullptr;
418  }
419 
420  private:
421  std::multimap<grpc::string_ref, grpc::string_ref>* recv_initial_metadata_;
422  grpc_metadata_array recv_initial_metadata_arr_;
423 };
424 
426  public:
427  CallOpClientRecvStatus() : recv_status_(nullptr) {}
428 
429  void ClientRecvStatus(ClientContext* context, Status* status) {
430  recv_trailing_metadata_ = &context->trailing_metadata_;
431  recv_status_ = status;
432  }
433 
434  protected:
435  void AddOp(grpc_op* ops, size_t* nops) {
436  if (recv_status_ == nullptr) return;
437  memset(&recv_trailing_metadata_arr_, 0,
438  sizeof(recv_trailing_metadata_arr_));
439  status_details_ = nullptr;
440  status_details_capacity_ = 0;
441  grpc_op* op = &ops[(*nops)++];
442  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
443  op->data.recv_status_on_client.trailing_metadata =
444  &recv_trailing_metadata_arr_;
445  op->data.recv_status_on_client.status = &status_code_;
446  op->data.recv_status_on_client.status_details = &status_details_;
447  op->data.recv_status_on_client.status_details_capacity =
448  &status_details_capacity_;
449  op->flags = 0;
450  op->reserved = NULL;
451  }
452 
453  void FinishOp(bool* status, int max_message_size) {
454  if (recv_status_ == nullptr) return;
455  FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
456  *recv_status_ = Status(
457  static_cast<StatusCode>(status_code_),
458  status_details_ ? grpc::string(status_details_) : grpc::string());
459  gpr_free(status_details_);
460  recv_status_ = nullptr;
461  }
462 
463  private:
464  std::multimap<grpc::string_ref, grpc::string_ref>* recv_trailing_metadata_;
465  Status* recv_status_;
466  grpc_metadata_array recv_trailing_metadata_arr_;
467  grpc_status_code status_code_;
468  char* status_details_;
469  size_t status_details_capacity_;
470 };
471 
478  public:
482  virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
483 
484  void set_max_message_size(int max_message_size) {
485  max_message_size_ = max_message_size;
486  }
487 
488  protected:
490 };
491 
498 template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
499  class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
500  class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
502  public Op1,
503  public Op2,
504  public Op3,
505  public Op4,
506  public Op5,
507  public Op6 {
508  public:
509  CallOpSet() : return_tag_(this) {}
510  void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE {
511  this->Op1::AddOp(ops, nops);
512  this->Op2::AddOp(ops, nops);
513  this->Op3::AddOp(ops, nops);
514  this->Op4::AddOp(ops, nops);
515  this->Op5::AddOp(ops, nops);
516  this->Op6::AddOp(ops, nops);
517  }
518 
519  bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
520  this->Op1::FinishOp(status, max_message_size_);
521  this->Op2::FinishOp(status, max_message_size_);
522  this->Op3::FinishOp(status, max_message_size_);
523  this->Op4::FinishOp(status, max_message_size_);
524  this->Op5::FinishOp(status, max_message_size_);
525  this->Op6::FinishOp(status, max_message_size_);
526  *tag = return_tag_;
527  return true;
528  }
529 
530  void set_output_tag(void* return_tag) { return_tag_ = return_tag; }
531 
532  private:
533  void* return_tag_;
534 };
535 
540 template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
541  class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
542  class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
543 class SneakyCallOpSet : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> {
544  public:
545  bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
547  return Base::FinalizeResult(tag, status) && false;
548  }
549 };
550 
551 // Channel and Server implement this to allow them to hook performing ops
552 class CallHook {
553  public:
554  virtual ~CallHook() {}
555  virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0;
556 };
557 
558 // Straightforward wrapping of the C call object
560  public:
561  /* call is owned by the caller */
562  Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq);
563  Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq,
564  int max_message_size);
565 
566  void PerformOps(CallOpSetInterface* ops);
567 
568  grpc_call* call() { return call_; }
569  CompletionQueue* cq() { return cq_; }
570 
571  int max_message_size() { return max_message_size_; }
572 
573  private:
574  CallHook* call_hook_;
575  CompletionQueue* cq_;
576  grpc_call* call_;
577  int max_message_size_;
578 };
579 
580 } // namespace grpc
581 
582 #endif // GRPCXX_IMPL_CALL_H
void ServerSendStatus(const std::multimap< grpc::string, grpc::string > &trailing_metadata, const Status &status)
Definition: call.h:356
Call(grpc_call *call, CallHook *call_hook_, CompletionQueue *cq)
CallOpRecvInitialMetadata()
Definition: call.h:397
void RecvMessage(R *message)
Definition: call.h:293
An interface allowing implementors to process and filter event tags.
Definition: completion_queue.h:192
WriteOptions & clear_buffer_hint()
Clears flag indicating that the write may be buffered and need not go out on the wire immediately...
Definition: call.h:112
Default argument for CallOpSet.
Definition: call.h:141
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:339
CallOpServerSendStatus()
Definition: call.h:354
void SendInitialMetadata(const std::multimap< grpc::string, grpc::string > &metadata)
Definition: call.h:151
WriteOptions & set_buffer_hint()
Sets flag indicating that the write may be buffered and need not go out on the wire immediately...
Definition: call.h:103
grpc::string error_message() const
Return the instance's error message.
Definition: status.h:64
CallOpSendMessage()
Definition: call.h:181
std::string string
Definition: config.h:112
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:301
CompletionQueue * cq()
Definition: call.h:569
void FinishOp(bool *status, int max_message_size)
Definition: call.h:310
WriteOptions & clear_no_compression()
Clears flag for the disabling of compression for the next message write.
Definition: call.h:86
int max_message_size_
Definition: call.h:489
bool FinalizeResult(void **tag, bool *status) GRPC_OVERRIDE
Definition: call.h:545
An abstract collection of call ops, used to generate the grpc_call_op structure to pass down to the l...
Definition: call.h:477
Definition: call.h:425
void FinishOp(bool *status, int max_message_size)
Definition: call.h:346
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:236
bool FinalizeResult(void **tag, bool *status) GRPC_OVERRIDE
Definition: call.h:519
void Clear()
Clear all flags.
Definition: call.h:70
void FinishOp(bool *status, int max_message_size)
Definition: call.h:203
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:367
WriteOptions()
Definition: call.h:66
Definition: call.h:352
#define GRPC_FINAL
Definition: config.h:71
void FillOps(grpc_op *ops, size_t *nops) GRPC_OVERRIDE
Fills in grpc_op, starting from ops[*nops] and moving upwards.
Definition: call.h:510
grpc_metadata * FillMetadataArray(const std::multimap< grpc::string, grpc::string > &metadata)
grpc_call * call()
Definition: call.h:568
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:159
WriteOptions & set_no_compression()
Sets flag for the disabling of compression for the next message write.
Definition: call.h:78
Definition: client_context.h:150
WriteOptions & operator=(const WriteOptions &rhs)
Definition: call.h:123
gpr_uint32 flags() const
Returns raw flags bitset.
Definition: call.h:73
void FinishOp(bool *status, int max_message_size)
Definition: call.h:453
Defines how to serialize and deserialize some type.
Definition: serialization_traits.h:64
Definition: call.h:179
bool send_
Definition: call.h:174
CallOpClientRecvStatus()
Definition: call.h:427
bool get_no_compression() const
Get value for the flag indicating whether compression for the next message write is forcefully disabl...
Definition: call.h:95
Status Deserialize(grpc_byte_buffer *buf, int max_message_size) GRPC_OVERRIDE
Definition: call.h:278
CallOpSet()
Definition: call.h:509
void FinishOp(bool *status, int max_message_size)
Definition: call.h:381
Definition: call.h:332
CallOpSendInitialMetadata()
Definition: call.h:149
void FillMetadataMap(grpc_metadata_array *arr, std::multimap< grpc::string_ref, grpc::string_ref > *metadata)
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:435
Definition: call.h:559
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:143
void FinishOp(bool *status, int max_message_size)
Definition: call.h:414
CallOpSetInterface()
Definition: call.h:479
WriteOptions(const WriteOptions &other)
Definition: call.h:67
Primary implementaiton of CallOpSetInterface.
Definition: call.h:501
void ClientSendClose()
Definition: call.h:336
Definition: call.h:227
int max_message_size()
Definition: call.h:571
Per-message write options.
Definition: call.h:64
CallOpClientSendClose()
Definition: call.h:334
bool get_buffer_hint() const
Get value for the flag indicating that the write may be buffered and need not go out on the wire imme...
Definition: call.h:121
CallOpRecvMessage()
Definition: call.h:229
StatusCode error_code() const
Return the instance's error code.
Definition: status.h:62
A thin wrapper around grpc_completion_queue (see / src/core/surface/completion_queue.h).
Definition: completion_queue.h:81
Status SendMessage(const M &message, const WriteOptions &options) GRPC_MUST_USE_RESULT
Send message using options for the write.
Definition: call.h:215
virtual void PerformOpsOnCall(CallOpSetInterface *ops, Call *call)=0
void FinishOp(bool *status, int max_message_size)
Definition: call.h:144
bool got_message
Definition: call.h:233
void ClientRecvStatus(ClientContext *context, Status *status)
Definition: call.h:429
void PerformOps(CallOpSetInterface *ops)
void FinishOp(bool *status, int max_message_size)
Definition: call.h:245
void set_max_message_size(int max_message_size)
Definition: call.h:484
DeserializeFuncType(R *message)
Definition: call.h:277
Did it work? If it didn't, why?
Definition: status.h:45
Definition: call.h:147
virtual Status Deserialize(grpc_byte_buffer *buf, int max_message_size)=0
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:405
void RecvMessage(R *message)
Definition: call.h:231
CallOpGenericRecvMessage()
Definition: call.h:290
bool got_message
Definition: call.h:298
A CallOpSet that does not post completions to the completion queue.
Definition: call.h:543
virtual void FillOps(grpc_op *ops, size_t *nops)=0
Fills in grpc_op, starting from ops[*nops] and moving upwards.
void set_output_tag(void *return_tag)
Definition: call.h:530
size_t initial_metadata_count_
Definition: call.h:175
#define GRPC_OVERRIDE
Definition: config.h:77
Definition: call.h:552
void RecvInitialMetadata(ClientContext *context)
Definition: call.h:399
Definition: call.h:395
void AddOp(grpc_op *ops, size_t *nops)
Definition: call.h:193
grpc_metadata * initial_metadata_
Definition: call.h:176
void FinishOp(bool *status, int max_message_size)
Definition: call.h:168
Definition: call.h:288
virtual ~CallHook()
Definition: call.h:554