call_op_set.h 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  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. #ifndef GRPCPP_IMPL_CALL_OP_SET_H
  19. #define GRPCPP_IMPL_CALL_OP_SET_H
  20. #include <cstring>
  21. #include <map>
  22. #include <memory>
  23. #include <grpc/grpc.h>
  24. #include <grpc/impl/compression_types.h>
  25. #include <grpc/impl/grpc_types.h>
  26. #include <grpc/slice.h>
  27. #include <grpc/support/alloc.h>
  28. #include <grpc/support/log.h>
  29. #include <grpcpp/client_context.h>
  30. #include <grpcpp/completion_queue.h>
  31. #include <grpcpp/impl/call.h>
  32. #include <grpcpp/impl/call_hook.h>
  33. #include <grpcpp/impl/call_op_set_interface.h>
  34. #include <grpcpp/impl/codegen/intercepted_channel.h>
  35. #include <grpcpp/impl/completion_queue_tag.h>
  36. #include <grpcpp/impl/interceptor_common.h>
  37. #include <grpcpp/impl/serialization_traits.h>
  38. #include <grpcpp/support/byte_buffer.h>
  39. #include <grpcpp/support/config.h>
  40. #include <grpcpp/support/slice.h>
  41. #include <grpcpp/support/string_ref.h>
  42. namespace grpc {
  43. namespace internal {
  44. class Call;
  45. class CallHook;
  46. // TODO(yangg) if the map is changed before we send, the pointers will be a
  47. // mess. Make sure it does not happen.
  48. inline grpc_metadata* FillMetadataArray(
  49. const std::multimap<TString, TString>& metadata,
  50. size_t* metadata_count, const TString& optional_error_details) {
  51. *metadata_count = metadata.size() + (optional_error_details.empty() ? 0 : 1);
  52. if (*metadata_count == 0) {
  53. return nullptr;
  54. }
  55. grpc_metadata* metadata_array = static_cast<grpc_metadata*>(
  56. gpr_malloc((*metadata_count) * sizeof(grpc_metadata)));
  57. size_t i = 0;
  58. for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
  59. metadata_array[i].key = SliceReferencingString(iter->first);
  60. metadata_array[i].value = SliceReferencingString(iter->second);
  61. }
  62. if (!optional_error_details.empty()) {
  63. metadata_array[i].key = grpc_slice_from_static_buffer(
  64. kBinaryErrorDetailsKey, sizeof(kBinaryErrorDetailsKey) - 1);
  65. metadata_array[i].value = SliceReferencingString(optional_error_details);
  66. }
  67. return metadata_array;
  68. }
  69. } // namespace internal
  70. /// Per-message write options.
  71. class WriteOptions {
  72. public:
  73. WriteOptions() : flags_(0), last_message_(false) {}
  74. /// Clear all flags.
  75. inline void Clear() { flags_ = 0; }
  76. /// Returns raw flags bitset.
  77. inline uint32_t flags() const { return flags_; }
  78. /// Sets flag for the disabling of compression for the next message write.
  79. ///
  80. /// \sa GRPC_WRITE_NO_COMPRESS
  81. inline WriteOptions& set_no_compression() {
  82. SetBit(GRPC_WRITE_NO_COMPRESS);
  83. return *this;
  84. }
  85. /// Clears flag for the disabling of compression for the next message write.
  86. ///
  87. /// \sa GRPC_WRITE_NO_COMPRESS
  88. inline WriteOptions& clear_no_compression() {
  89. ClearBit(GRPC_WRITE_NO_COMPRESS);
  90. return *this;
  91. }
  92. /// Get value for the flag indicating whether compression for the next
  93. /// message write is forcefully disabled.
  94. ///
  95. /// \sa GRPC_WRITE_NO_COMPRESS
  96. inline bool get_no_compression() const {
  97. return GetBit(GRPC_WRITE_NO_COMPRESS);
  98. }
  99. /// Sets flag indicating that the write may be buffered and need not go out on
  100. /// the wire immediately.
  101. ///
  102. /// \sa GRPC_WRITE_BUFFER_HINT
  103. inline WriteOptions& set_buffer_hint() {
  104. SetBit(GRPC_WRITE_BUFFER_HINT);
  105. return *this;
  106. }
  107. /// Clears flag indicating that the write may be buffered and need not go out
  108. /// on the wire immediately.
  109. ///
  110. /// \sa GRPC_WRITE_BUFFER_HINT
  111. inline WriteOptions& clear_buffer_hint() {
  112. ClearBit(GRPC_WRITE_BUFFER_HINT);
  113. return *this;
  114. }
  115. /// Get value for the flag indicating that the write may be buffered and need
  116. /// not go out on the wire immediately.
  117. ///
  118. /// \sa GRPC_WRITE_BUFFER_HINT
  119. inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
  120. /// corked bit: aliases set_buffer_hint currently, with the intent that
  121. /// set_buffer_hint will be removed in the future
  122. inline WriteOptions& set_corked() {
  123. SetBit(GRPC_WRITE_BUFFER_HINT);
  124. return *this;
  125. }
  126. inline WriteOptions& clear_corked() {
  127. ClearBit(GRPC_WRITE_BUFFER_HINT);
  128. return *this;
  129. }
  130. inline bool is_corked() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
  131. /// last-message bit: indicates this is the last message in a stream
  132. /// client-side: makes Write the equivalent of performing Write, WritesDone
  133. /// in a single step
  134. /// server-side: hold the Write until the service handler returns (sync api)
  135. /// or until Finish is called (async api)
  136. inline WriteOptions& set_last_message() {
  137. last_message_ = true;
  138. return *this;
  139. }
  140. /// Clears flag indicating that this is the last message in a stream,
  141. /// disabling coalescing.
  142. inline WriteOptions& clear_last_message() {
  143. last_message_ = false;
  144. return *this;
  145. }
  146. /// Get value for the flag indicating that this is the last message, and
  147. /// should be coalesced with trailing metadata.
  148. ///
  149. /// \sa GRPC_WRITE_LAST_MESSAGE
  150. bool is_last_message() const { return last_message_; }
  151. /// Guarantee that all bytes have been written to the socket before completing
  152. /// this write (usually writes are completed when they pass flow control).
  153. inline WriteOptions& set_write_through() {
  154. SetBit(GRPC_WRITE_THROUGH);
  155. return *this;
  156. }
  157. inline WriteOptions& clear_write_through() {
  158. ClearBit(GRPC_WRITE_THROUGH);
  159. return *this;
  160. }
  161. inline bool is_write_through() const { return GetBit(GRPC_WRITE_THROUGH); }
  162. private:
  163. void SetBit(const uint32_t mask) { flags_ |= mask; }
  164. void ClearBit(const uint32_t mask) { flags_ &= ~mask; }
  165. bool GetBit(const uint32_t mask) const { return (flags_ & mask) != 0; }
  166. uint32_t flags_;
  167. bool last_message_;
  168. };
  169. namespace internal {
  170. /// Default argument for CallOpSet. The Unused parameter is unused by
  171. /// the class, but can be used for generating multiple names for the
  172. /// same thing.
  173. template <int Unused>
  174. class CallNoOp {
  175. protected:
  176. void AddOp(grpc_op* /*ops*/, size_t* /*nops*/) {}
  177. void FinishOp(bool* /*status*/) {}
  178. void SetInterceptionHookPoint(
  179. InterceptorBatchMethodsImpl* /*interceptor_methods*/) {}
  180. void SetFinishInterceptionHookPoint(
  181. InterceptorBatchMethodsImpl* /*interceptor_methods*/) {}
  182. void SetHijackingState(InterceptorBatchMethodsImpl* /*interceptor_methods*/) {
  183. }
  184. };
  185. class CallOpSendInitialMetadata {
  186. public:
  187. CallOpSendInitialMetadata() : send_(false) {
  188. maybe_compression_level_.is_set = false;
  189. }
  190. void SendInitialMetadata(std::multimap<TString, TString>* metadata,
  191. uint32_t flags) {
  192. maybe_compression_level_.is_set = false;
  193. send_ = true;
  194. flags_ = flags;
  195. metadata_map_ = metadata;
  196. }
  197. void set_compression_level(grpc_compression_level level) {
  198. maybe_compression_level_.is_set = true;
  199. maybe_compression_level_.level = level;
  200. }
  201. protected:
  202. void AddOp(grpc_op* ops, size_t* nops) {
  203. if (!send_ || hijacked_) return;
  204. grpc_op* op = &ops[(*nops)++];
  205. op->op = GRPC_OP_SEND_INITIAL_METADATA;
  206. op->flags = flags_;
  207. op->reserved = nullptr;
  208. initial_metadata_ =
  209. FillMetadataArray(*metadata_map_, &initial_metadata_count_, "");
  210. op->data.send_initial_metadata.count = initial_metadata_count_;
  211. op->data.send_initial_metadata.metadata = initial_metadata_;
  212. op->data.send_initial_metadata.maybe_compression_level.is_set =
  213. maybe_compression_level_.is_set;
  214. if (maybe_compression_level_.is_set) {
  215. op->data.send_initial_metadata.maybe_compression_level.level =
  216. maybe_compression_level_.level;
  217. }
  218. }
  219. void FinishOp(bool* /*status*/) {
  220. if (!send_ || hijacked_) return;
  221. gpr_free(initial_metadata_);
  222. send_ = false;
  223. }
  224. void SetInterceptionHookPoint(
  225. InterceptorBatchMethodsImpl* interceptor_methods) {
  226. if (!send_) return;
  227. interceptor_methods->AddInterceptionHookPoint(
  228. experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA);
  229. interceptor_methods->SetSendInitialMetadata(metadata_map_);
  230. }
  231. void SetFinishInterceptionHookPoint(
  232. InterceptorBatchMethodsImpl* /*interceptor_methods*/) {}
  233. void SetHijackingState(InterceptorBatchMethodsImpl* /*interceptor_methods*/) {
  234. hijacked_ = true;
  235. }
  236. bool hijacked_ = false;
  237. bool send_;
  238. uint32_t flags_;
  239. size_t initial_metadata_count_;
  240. std::multimap<TString, TString>* metadata_map_;
  241. grpc_metadata* initial_metadata_;
  242. struct {
  243. bool is_set;
  244. grpc_compression_level level;
  245. } maybe_compression_level_;
  246. };
  247. // win headers create macro SendMessage
  248. #if defined(_WIN32) && defined(SendMessage)
  249. #undef SendMessage
  250. #endif
  251. class CallOpSendMessage {
  252. public:
  253. CallOpSendMessage() : send_buf_() {}
  254. /// Send \a message using \a options for the write. The \a options are cleared
  255. /// after use.
  256. template <class M>
  257. Status SendMessage(const M& message,
  258. WriteOptions options) GRPC_MUST_USE_RESULT;
  259. template <class M>
  260. Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
  261. /// Send \a message using \a options for the write. The \a options are cleared
  262. /// after use. This form of SendMessage allows gRPC to reference \a message
  263. /// beyond the lifetime of SendMessage.
  264. template <class M>
  265. Status SendMessagePtr(const M* message,
  266. WriteOptions options) GRPC_MUST_USE_RESULT;
  267. /// This form of SendMessage allows gRPC to reference \a message beyond the
  268. /// lifetime of SendMessage.
  269. template <class M>
  270. Status SendMessagePtr(const M* message) GRPC_MUST_USE_RESULT;
  271. protected:
  272. void AddOp(grpc_op* ops, size_t* nops) {
  273. if (msg_ == nullptr && !send_buf_.Valid()) return;
  274. if (hijacked_) {
  275. serializer_ = nullptr;
  276. return;
  277. }
  278. if (msg_ != nullptr) {
  279. GPR_ASSERT(serializer_(msg_).ok());
  280. }
  281. serializer_ = nullptr;
  282. grpc_op* op = &ops[(*nops)++];
  283. op->op = GRPC_OP_SEND_MESSAGE;
  284. op->flags = write_options_.flags();
  285. op->reserved = nullptr;
  286. op->data.send_message.send_message = send_buf_.c_buffer();
  287. // Flags are per-message: clear them after use.
  288. write_options_.Clear();
  289. }
  290. void FinishOp(bool* status) {
  291. if (msg_ == nullptr && !send_buf_.Valid()) return;
  292. send_buf_.Clear();
  293. if (hijacked_ && failed_send_) {
  294. // Hijacking interceptor failed this Op
  295. *status = false;
  296. } else if (!*status) {
  297. // This Op was passed down to core and the Op failed
  298. failed_send_ = true;
  299. }
  300. }
  301. void SetInterceptionHookPoint(
  302. InterceptorBatchMethodsImpl* interceptor_methods) {
  303. if (msg_ == nullptr && !send_buf_.Valid()) return;
  304. interceptor_methods->AddInterceptionHookPoint(
  305. experimental::InterceptionHookPoints::PRE_SEND_MESSAGE);
  306. interceptor_methods->SetSendMessage(&send_buf_, &msg_, &failed_send_,
  307. serializer_);
  308. }
  309. void SetFinishInterceptionHookPoint(
  310. InterceptorBatchMethodsImpl* interceptor_methods) {
  311. if (msg_ != nullptr || send_buf_.Valid()) {
  312. interceptor_methods->AddInterceptionHookPoint(
  313. experimental::InterceptionHookPoints::POST_SEND_MESSAGE);
  314. }
  315. send_buf_.Clear();
  316. msg_ = nullptr;
  317. // The contents of the SendMessage value that was previously set
  318. // has had its references stolen by core's operations
  319. interceptor_methods->SetSendMessage(nullptr, nullptr, &failed_send_,
  320. nullptr);
  321. }
  322. void SetHijackingState(InterceptorBatchMethodsImpl* /*interceptor_methods*/) {
  323. hijacked_ = true;
  324. }
  325. private:
  326. const void* msg_ = nullptr; // The original non-serialized message
  327. bool hijacked_ = false;
  328. bool failed_send_ = false;
  329. ByteBuffer send_buf_;
  330. WriteOptions write_options_;
  331. std::function<Status(const void*)> serializer_;
  332. };
  333. template <class M>
  334. Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) {
  335. write_options_ = options;
  336. // Serialize immediately since we do not have access to the message pointer
  337. bool own_buf;
  338. Status result = SerializationTraits<M>::Serialize(
  339. message, send_buf_.bbuf_ptr(), &own_buf);
  340. if (!own_buf) {
  341. send_buf_.Duplicate();
  342. }
  343. return result;
  344. }
  345. template <class M>
  346. Status CallOpSendMessage::SendMessage(const M& message) {
  347. return SendMessage(message, WriteOptions());
  348. }
  349. template <class M>
  350. Status CallOpSendMessage::SendMessagePtr(const M* message,
  351. WriteOptions options) {
  352. msg_ = message;
  353. write_options_ = options;
  354. // Store the serializer for later since we have access to the message
  355. serializer_ = [this](const void* message) {
  356. bool own_buf;
  357. // TODO(vjpai): Remove the void below when possible
  358. // The void in the template parameter below should not be needed
  359. // (since it should be implicit) but is needed due to an observed
  360. // difference in behavior between clang and gcc for certain internal users
  361. Status result = SerializationTraits<M>::Serialize(
  362. *static_cast<const M*>(message), send_buf_.bbuf_ptr(), &own_buf);
  363. if (!own_buf) {
  364. send_buf_.Duplicate();
  365. }
  366. return result;
  367. };
  368. return Status();
  369. }
  370. template <class M>
  371. Status CallOpSendMessage::SendMessagePtr(const M* message) {
  372. return SendMessagePtr(message, WriteOptions());
  373. }
  374. template <class R>
  375. class CallOpRecvMessage {
  376. public:
  377. void RecvMessage(R* message) { message_ = message; }
  378. // Do not change status if no message is received.
  379. void AllowNoMessage() { allow_not_getting_message_ = true; }
  380. bool got_message = false;
  381. protected:
  382. void AddOp(grpc_op* ops, size_t* nops) {
  383. if (message_ == nullptr || hijacked_) return;
  384. grpc_op* op = &ops[(*nops)++];
  385. op->op = GRPC_OP_RECV_MESSAGE;
  386. op->flags = 0;
  387. op->reserved = nullptr;
  388. op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
  389. }
  390. void FinishOp(bool* status) {
  391. if (message_ == nullptr) return;
  392. if (recv_buf_.Valid()) {
  393. if (*status) {
  394. got_message = *status =
  395. SerializationTraits<R>::Deserialize(recv_buf_.bbuf_ptr(), message_)
  396. .ok();
  397. recv_buf_.Release();
  398. } else {
  399. got_message = false;
  400. recv_buf_.Clear();
  401. }
  402. } else if (hijacked_) {
  403. if (hijacked_recv_message_failed_) {
  404. FinishOpRecvMessageFailureHandler(status);
  405. } else {
  406. // The op was hijacked and it was successful. There is no further action
  407. // to be performed since the message is already in its non-serialized
  408. // form.
  409. }
  410. } else {
  411. FinishOpRecvMessageFailureHandler(status);
  412. }
  413. }
  414. void SetInterceptionHookPoint(
  415. InterceptorBatchMethodsImpl* interceptor_methods) {
  416. if (message_ == nullptr) return;
  417. interceptor_methods->SetRecvMessage(message_,
  418. &hijacked_recv_message_failed_);
  419. }
  420. void SetFinishInterceptionHookPoint(
  421. InterceptorBatchMethodsImpl* interceptor_methods) {
  422. if (message_ == nullptr) return;
  423. interceptor_methods->AddInterceptionHookPoint(
  424. experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
  425. if (!got_message) interceptor_methods->SetRecvMessage(nullptr, nullptr);
  426. }
  427. void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
  428. hijacked_ = true;
  429. if (message_ == nullptr) return;
  430. interceptor_methods->AddInterceptionHookPoint(
  431. experimental::InterceptionHookPoints::PRE_RECV_MESSAGE);
  432. got_message = true;
  433. }
  434. private:
  435. // Sets got_message and \a status for a failed recv message op
  436. void FinishOpRecvMessageFailureHandler(bool* status) {
  437. got_message = false;
  438. if (!allow_not_getting_message_) {
  439. *status = false;
  440. }
  441. }
  442. R* message_ = nullptr;
  443. ByteBuffer recv_buf_;
  444. bool allow_not_getting_message_ = false;
  445. bool hijacked_ = false;
  446. bool hijacked_recv_message_failed_ = false;
  447. };
  448. class DeserializeFunc {
  449. public:
  450. virtual Status Deserialize(ByteBuffer* buf) = 0;
  451. virtual ~DeserializeFunc() {}
  452. };
  453. template <class R>
  454. class DeserializeFuncType final : public DeserializeFunc {
  455. public:
  456. explicit DeserializeFuncType(R* message) : message_(message) {}
  457. Status Deserialize(ByteBuffer* buf) override {
  458. return SerializationTraits<R>::Deserialize(buf->bbuf_ptr(), message_);
  459. }
  460. ~DeserializeFuncType() override {}
  461. private:
  462. R* message_; // Not a managed pointer because management is external to this
  463. };
  464. class CallOpGenericRecvMessage {
  465. public:
  466. template <class R>
  467. void RecvMessage(R* message) {
  468. // Use an explicit base class pointer to avoid resolution error in the
  469. // following unique_ptr::reset for some old implementations.
  470. DeserializeFunc* func = new DeserializeFuncType<R>(message);
  471. deserialize_.reset(func);
  472. message_ = message;
  473. }
  474. // Do not change status if no message is received.
  475. void AllowNoMessage() { allow_not_getting_message_ = true; }
  476. bool got_message = false;
  477. protected:
  478. void AddOp(grpc_op* ops, size_t* nops) {
  479. if (!deserialize_ || hijacked_) return;
  480. grpc_op* op = &ops[(*nops)++];
  481. op->op = GRPC_OP_RECV_MESSAGE;
  482. op->flags = 0;
  483. op->reserved = nullptr;
  484. op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
  485. }
  486. void FinishOp(bool* status) {
  487. if (!deserialize_) return;
  488. if (recv_buf_.Valid()) {
  489. if (*status) {
  490. got_message = true;
  491. *status = deserialize_->Deserialize(&recv_buf_).ok();
  492. recv_buf_.Release();
  493. } else {
  494. got_message = false;
  495. recv_buf_.Clear();
  496. }
  497. } else if (hijacked_) {
  498. if (hijacked_recv_message_failed_) {
  499. FinishOpRecvMessageFailureHandler(status);
  500. } else {
  501. // The op was hijacked and it was successful. There is no further action
  502. // to be performed since the message is already in its non-serialized
  503. // form.
  504. }
  505. } else {
  506. got_message = false;
  507. if (!allow_not_getting_message_) {
  508. *status = false;
  509. }
  510. }
  511. }
  512. void SetInterceptionHookPoint(
  513. InterceptorBatchMethodsImpl* interceptor_methods) {
  514. if (!deserialize_) return;
  515. interceptor_methods->SetRecvMessage(message_,
  516. &hijacked_recv_message_failed_);
  517. }
  518. void SetFinishInterceptionHookPoint(
  519. InterceptorBatchMethodsImpl* interceptor_methods) {
  520. if (!deserialize_) return;
  521. interceptor_methods->AddInterceptionHookPoint(
  522. experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
  523. if (!got_message) interceptor_methods->SetRecvMessage(nullptr, nullptr);
  524. deserialize_.reset();
  525. }
  526. void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
  527. hijacked_ = true;
  528. if (!deserialize_) return;
  529. interceptor_methods->AddInterceptionHookPoint(
  530. experimental::InterceptionHookPoints::PRE_RECV_MESSAGE);
  531. got_message = true;
  532. }
  533. private:
  534. // Sets got_message and \a status for a failed recv message op
  535. void FinishOpRecvMessageFailureHandler(bool* status) {
  536. got_message = false;
  537. if (!allow_not_getting_message_) {
  538. *status = false;
  539. }
  540. }
  541. void* message_ = nullptr;
  542. std::unique_ptr<DeserializeFunc> deserialize_;
  543. ByteBuffer recv_buf_;
  544. bool allow_not_getting_message_ = false;
  545. bool hijacked_ = false;
  546. bool hijacked_recv_message_failed_ = false;
  547. };
  548. class CallOpClientSendClose {
  549. public:
  550. CallOpClientSendClose() : send_(false) {}
  551. void ClientSendClose() { send_ = true; }
  552. protected:
  553. void AddOp(grpc_op* ops, size_t* nops) {
  554. if (!send_ || hijacked_) return;
  555. grpc_op* op = &ops[(*nops)++];
  556. op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  557. op->flags = 0;
  558. op->reserved = nullptr;
  559. }
  560. void FinishOp(bool* /*status*/) { send_ = false; }
  561. void SetInterceptionHookPoint(
  562. InterceptorBatchMethodsImpl* interceptor_methods) {
  563. if (!send_) return;
  564. interceptor_methods->AddInterceptionHookPoint(
  565. experimental::InterceptionHookPoints::PRE_SEND_CLOSE);
  566. }
  567. void SetFinishInterceptionHookPoint(
  568. InterceptorBatchMethodsImpl* /*interceptor_methods*/) {}
  569. void SetHijackingState(InterceptorBatchMethodsImpl* /*interceptor_methods*/) {
  570. hijacked_ = true;
  571. }
  572. private:
  573. bool hijacked_ = false;
  574. bool send_;
  575. };
  576. class CallOpServerSendStatus {
  577. public:
  578. CallOpServerSendStatus() : send_status_available_(false) {}
  579. void ServerSendStatus(
  580. std::multimap<TString, TString>* trailing_metadata,
  581. const Status& status) {
  582. send_error_details_ = status.error_details();
  583. metadata_map_ = trailing_metadata;
  584. send_status_available_ = true;
  585. send_status_code_ = static_cast<grpc_status_code>(status.error_code());
  586. send_error_message_ = status.error_message();
  587. }
  588. protected:
  589. void AddOp(grpc_op* ops, size_t* nops) {
  590. if (!send_status_available_ || hijacked_) return;
  591. trailing_metadata_ = FillMetadataArray(
  592. *metadata_map_, &trailing_metadata_count_, send_error_details_);
  593. grpc_op* op = &ops[(*nops)++];
  594. op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
  595. op->data.send_status_from_server.trailing_metadata_count =
  596. trailing_metadata_count_;
  597. op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
  598. op->data.send_status_from_server.status = send_status_code_;
  599. error_message_slice_ = SliceReferencingString(send_error_message_);
  600. op->data.send_status_from_server.status_details =
  601. send_error_message_.empty() ? nullptr : &error_message_slice_;
  602. op->flags = 0;
  603. op->reserved = nullptr;
  604. }
  605. void FinishOp(bool* /*status*/) {
  606. if (!send_status_available_ || hijacked_) return;
  607. gpr_free(trailing_metadata_);
  608. send_status_available_ = false;
  609. }
  610. void SetInterceptionHookPoint(
  611. InterceptorBatchMethodsImpl* interceptor_methods) {
  612. if (!send_status_available_) return;
  613. interceptor_methods->AddInterceptionHookPoint(
  614. experimental::InterceptionHookPoints::PRE_SEND_STATUS);
  615. interceptor_methods->SetSendTrailingMetadata(metadata_map_);
  616. interceptor_methods->SetSendStatus(&send_status_code_, &send_error_details_,
  617. &send_error_message_);
  618. }
  619. void SetFinishInterceptionHookPoint(
  620. InterceptorBatchMethodsImpl* /*interceptor_methods*/) {}
  621. void SetHijackingState(InterceptorBatchMethodsImpl* /*interceptor_methods*/) {
  622. hijacked_ = true;
  623. }
  624. private:
  625. bool hijacked_ = false;
  626. bool send_status_available_;
  627. grpc_status_code send_status_code_;
  628. TString send_error_details_;
  629. TString send_error_message_;
  630. size_t trailing_metadata_count_;
  631. std::multimap<TString, TString>* metadata_map_;
  632. grpc_metadata* trailing_metadata_;
  633. grpc_slice error_message_slice_;
  634. };
  635. class CallOpRecvInitialMetadata {
  636. public:
  637. CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
  638. void RecvInitialMetadata(grpc::ClientContext* context) {
  639. context->initial_metadata_received_ = true;
  640. metadata_map_ = &context->recv_initial_metadata_;
  641. }
  642. protected:
  643. void AddOp(grpc_op* ops, size_t* nops) {
  644. if (metadata_map_ == nullptr || hijacked_) return;
  645. grpc_op* op = &ops[(*nops)++];
  646. op->op = GRPC_OP_RECV_INITIAL_METADATA;
  647. op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr();
  648. op->flags = 0;
  649. op->reserved = nullptr;
  650. }
  651. void FinishOp(bool* /*status*/) {
  652. if (metadata_map_ == nullptr || hijacked_) return;
  653. }
  654. void SetInterceptionHookPoint(
  655. InterceptorBatchMethodsImpl* interceptor_methods) {
  656. interceptor_methods->SetRecvInitialMetadata(metadata_map_);
  657. }
  658. void SetFinishInterceptionHookPoint(
  659. InterceptorBatchMethodsImpl* interceptor_methods) {
  660. if (metadata_map_ == nullptr) return;
  661. interceptor_methods->AddInterceptionHookPoint(
  662. experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
  663. metadata_map_ = nullptr;
  664. }
  665. void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
  666. hijacked_ = true;
  667. if (metadata_map_ == nullptr) return;
  668. interceptor_methods->AddInterceptionHookPoint(
  669. experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA);
  670. }
  671. private:
  672. bool hijacked_ = false;
  673. MetadataMap* metadata_map_;
  674. };
  675. class CallOpClientRecvStatus {
  676. public:
  677. CallOpClientRecvStatus()
  678. : recv_status_(nullptr), debug_error_string_(nullptr) {}
  679. void ClientRecvStatus(grpc::ClientContext* context, Status* status) {
  680. client_context_ = context;
  681. metadata_map_ = &client_context_->trailing_metadata_;
  682. recv_status_ = status;
  683. error_message_ = grpc_empty_slice();
  684. }
  685. protected:
  686. void AddOp(grpc_op* ops, size_t* nops) {
  687. if (recv_status_ == nullptr || hijacked_) return;
  688. grpc_op* op = &ops[(*nops)++];
  689. op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  690. op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
  691. op->data.recv_status_on_client.status = &status_code_;
  692. op->data.recv_status_on_client.status_details = &error_message_;
  693. op->data.recv_status_on_client.error_string = &debug_error_string_;
  694. op->flags = 0;
  695. op->reserved = nullptr;
  696. }
  697. void FinishOp(bool* /*status*/) {
  698. if (recv_status_ == nullptr || hijacked_) return;
  699. if (static_cast<StatusCode>(status_code_) == StatusCode::OK) {
  700. *recv_status_ = Status();
  701. GPR_DEBUG_ASSERT(debug_error_string_ == nullptr);
  702. } else {
  703. *recv_status_ =
  704. Status(static_cast<StatusCode>(status_code_),
  705. GRPC_SLICE_IS_EMPTY(error_message_)
  706. ? TString()
  707. : TString(reinterpret_cast<const char*>GRPC_SLICE_START_PTR(error_message_),
  708. reinterpret_cast<const char*>GRPC_SLICE_END_PTR(error_message_)),
  709. metadata_map_->GetBinaryErrorDetails());
  710. if (debug_error_string_ != nullptr) {
  711. client_context_->set_debug_error_string(debug_error_string_);
  712. gpr_free(const_cast<char*>(debug_error_string_));
  713. }
  714. }
  715. // TODO(soheil): Find callers that set debug string even for status OK,
  716. // and fix them.
  717. grpc_slice_unref(error_message_);
  718. }
  719. void SetInterceptionHookPoint(
  720. InterceptorBatchMethodsImpl* interceptor_methods) {
  721. interceptor_methods->SetRecvStatus(recv_status_);
  722. interceptor_methods->SetRecvTrailingMetadata(metadata_map_);
  723. }
  724. void SetFinishInterceptionHookPoint(
  725. InterceptorBatchMethodsImpl* interceptor_methods) {
  726. if (recv_status_ == nullptr) return;
  727. interceptor_methods->AddInterceptionHookPoint(
  728. experimental::InterceptionHookPoints::POST_RECV_STATUS);
  729. recv_status_ = nullptr;
  730. }
  731. void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
  732. hijacked_ = true;
  733. if (recv_status_ == nullptr) return;
  734. interceptor_methods->AddInterceptionHookPoint(
  735. experimental::InterceptionHookPoints::PRE_RECV_STATUS);
  736. }
  737. private:
  738. bool hijacked_ = false;
  739. grpc::ClientContext* client_context_;
  740. MetadataMap* metadata_map_;
  741. Status* recv_status_;
  742. const char* debug_error_string_;
  743. grpc_status_code status_code_;
  744. grpc_slice error_message_;
  745. };
  746. template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
  747. class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
  748. class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
  749. class CallOpSet;
  750. /// Primary implementation of CallOpSetInterface.
  751. /// Since we cannot use variadic templates, we declare slots up to
  752. /// the maximum count of ops we'll need in a set. We leverage the
  753. /// empty base class optimization to slim this class (especially
  754. /// when there are many unused slots used). To avoid duplicate base classes,
  755. /// the template parameter for CallNoOp is varied by argument position.
  756. template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
  757. class CallOpSet : public CallOpSetInterface,
  758. public Op1,
  759. public Op2,
  760. public Op3,
  761. public Op4,
  762. public Op5,
  763. public Op6 {
  764. public:
  765. CallOpSet() : core_cq_tag_(this), return_tag_(this) {}
  766. // The copy constructor and assignment operator reset the value of
  767. // core_cq_tag_, return_tag_, done_intercepting_ and interceptor_methods_
  768. // since those are only meaningful on a specific object, not across objects.
  769. CallOpSet(const CallOpSet& other)
  770. : core_cq_tag_(this),
  771. return_tag_(this),
  772. call_(other.call_),
  773. done_intercepting_(false),
  774. interceptor_methods_(InterceptorBatchMethodsImpl()) {}
  775. CallOpSet& operator=(const CallOpSet& other) {
  776. if (&other == this) {
  777. return *this;
  778. }
  779. core_cq_tag_ = this;
  780. return_tag_ = this;
  781. call_ = other.call_;
  782. done_intercepting_ = false;
  783. interceptor_methods_ = InterceptorBatchMethodsImpl();
  784. return *this;
  785. }
  786. void FillOps(Call* call) override {
  787. done_intercepting_ = false;
  788. grpc_call_ref(call->call());
  789. call_ =
  790. *call; // It's fine to create a copy of call since it's just pointers
  791. if (RunInterceptors()) {
  792. ContinueFillOpsAfterInterception();
  793. } else {
  794. // After the interceptors are run, ContinueFillOpsAfterInterception will
  795. // be run
  796. }
  797. }
  798. bool FinalizeResult(void** tag, bool* status) override {
  799. if (done_intercepting_) {
  800. // Complete the avalanching since we are done with this batch of ops
  801. call_.cq()->CompleteAvalanching();
  802. // We have already finished intercepting and filling in the results. This
  803. // round trip from the core needed to be made because interceptors were
  804. // run
  805. *tag = return_tag_;
  806. *status = saved_status_;
  807. grpc_call_unref(call_.call());
  808. return true;
  809. }
  810. this->Op1::FinishOp(status);
  811. this->Op2::FinishOp(status);
  812. this->Op3::FinishOp(status);
  813. this->Op4::FinishOp(status);
  814. this->Op5::FinishOp(status);
  815. this->Op6::FinishOp(status);
  816. saved_status_ = *status;
  817. if (RunInterceptorsPostRecv()) {
  818. *tag = return_tag_;
  819. grpc_call_unref(call_.call());
  820. return true;
  821. }
  822. // Interceptors are going to be run, so we can't return the tag just yet.
  823. // After the interceptors are run, ContinueFinalizeResultAfterInterception
  824. return false;
  825. }
  826. void set_output_tag(void* return_tag) { return_tag_ = return_tag; }
  827. void* core_cq_tag() override { return core_cq_tag_; }
  828. /// set_core_cq_tag is used to provide a different core CQ tag than "this".
  829. /// This is used for callback-based tags, where the core tag is the core
  830. /// callback function. It does not change the use or behavior of any other
  831. /// function (such as FinalizeResult)
  832. void set_core_cq_tag(void* core_cq_tag) { core_cq_tag_ = core_cq_tag; }
  833. // This will be called while interceptors are run if the RPC is a hijacked
  834. // RPC. This should set hijacking state for each of the ops.
  835. void SetHijackingState() override {
  836. this->Op1::SetHijackingState(&interceptor_methods_);
  837. this->Op2::SetHijackingState(&interceptor_methods_);
  838. this->Op3::SetHijackingState(&interceptor_methods_);
  839. this->Op4::SetHijackingState(&interceptor_methods_);
  840. this->Op5::SetHijackingState(&interceptor_methods_);
  841. this->Op6::SetHijackingState(&interceptor_methods_);
  842. }
  843. // Should be called after interceptors are done running
  844. void ContinueFillOpsAfterInterception() override {
  845. static const size_t MAX_OPS = 6;
  846. grpc_op ops[MAX_OPS];
  847. size_t nops = 0;
  848. this->Op1::AddOp(ops, &nops);
  849. this->Op2::AddOp(ops, &nops);
  850. this->Op3::AddOp(ops, &nops);
  851. this->Op4::AddOp(ops, &nops);
  852. this->Op5::AddOp(ops, &nops);
  853. this->Op6::AddOp(ops, &nops);
  854. grpc_call_error err =
  855. grpc_call_start_batch(call_.call(), ops, nops, core_cq_tag(), nullptr);
  856. if (err != GRPC_CALL_OK) {
  857. // A failure here indicates an API misuse; for example, doing a Write
  858. // while another Write is already pending on the same RPC or invoking
  859. // WritesDone multiple times
  860. gpr_log(GPR_ERROR, "API misuse of type %s observed",
  861. grpc_call_error_to_string(err));
  862. GPR_ASSERT(false);
  863. }
  864. }
  865. // Should be called after interceptors are done running on the finalize result
  866. // path
  867. void ContinueFinalizeResultAfterInterception() override {
  868. done_intercepting_ = true;
  869. // The following call_start_batch is internally-generated so no need for an
  870. // explanatory log on failure.
  871. GPR_ASSERT(grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag(),
  872. nullptr) == GRPC_CALL_OK);
  873. }
  874. private:
  875. // Returns true if no interceptors need to be run
  876. bool RunInterceptors() {
  877. interceptor_methods_.ClearState();
  878. interceptor_methods_.SetCallOpSetInterface(this);
  879. interceptor_methods_.SetCall(&call_);
  880. this->Op1::SetInterceptionHookPoint(&interceptor_methods_);
  881. this->Op2::SetInterceptionHookPoint(&interceptor_methods_);
  882. this->Op3::SetInterceptionHookPoint(&interceptor_methods_);
  883. this->Op4::SetInterceptionHookPoint(&interceptor_methods_);
  884. this->Op5::SetInterceptionHookPoint(&interceptor_methods_);
  885. this->Op6::SetInterceptionHookPoint(&interceptor_methods_);
  886. if (interceptor_methods_.InterceptorsListEmpty()) {
  887. return true;
  888. }
  889. // This call will go through interceptors and would need to
  890. // schedule new batches, so delay completion queue shutdown
  891. call_.cq()->RegisterAvalanching();
  892. return interceptor_methods_.RunInterceptors();
  893. }
  894. // Returns true if no interceptors need to be run
  895. bool RunInterceptorsPostRecv() {
  896. // Call and OpSet had already been set on the set state.
  897. // SetReverse also clears previously set hook points
  898. interceptor_methods_.SetReverse();
  899. this->Op1::SetFinishInterceptionHookPoint(&interceptor_methods_);
  900. this->Op2::SetFinishInterceptionHookPoint(&interceptor_methods_);
  901. this->Op3::SetFinishInterceptionHookPoint(&interceptor_methods_);
  902. this->Op4::SetFinishInterceptionHookPoint(&interceptor_methods_);
  903. this->Op5::SetFinishInterceptionHookPoint(&interceptor_methods_);
  904. this->Op6::SetFinishInterceptionHookPoint(&interceptor_methods_);
  905. return interceptor_methods_.RunInterceptors();
  906. }
  907. void* core_cq_tag_;
  908. void* return_tag_;
  909. Call call_;
  910. bool done_intercepting_ = false;
  911. InterceptorBatchMethodsImpl interceptor_methods_;
  912. bool saved_status_;
  913. };
  914. } // namespace internal
  915. } // namespace grpc
  916. #endif // GRPCPP_IMPL_CALL_OP_SET_H