call.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. #include <grpc++/impl/call.h>
  34. #include <grpc/support/alloc.h>
  35. #include <grpc++/byte_buffer.h>
  36. #include <grpc++/client_context.h>
  37. #include <grpc++/channel_interface.h>
  38. #include "src/cpp/proto/proto_utils.h"
  39. namespace grpc {
  40. CallOpBuffer::CallOpBuffer()
  41. : return_tag_(this),
  42. send_initial_metadata_(false),
  43. initial_metadata_count_(0),
  44. initial_metadata_(nullptr),
  45. recv_initial_metadata_(nullptr),
  46. recv_initial_metadata_arr_{0, 0, nullptr},
  47. send_message_(nullptr),
  48. send_message_buffer_(nullptr),
  49. send_buf_(nullptr),
  50. recv_message_(nullptr),
  51. recv_message_buffer_(nullptr),
  52. recv_buf_(nullptr),
  53. client_send_close_(false),
  54. recv_trailing_metadata_(nullptr),
  55. recv_status_(nullptr),
  56. recv_trailing_metadata_arr_{0, 0, nullptr},
  57. status_code_(GRPC_STATUS_OK),
  58. status_details_(nullptr),
  59. status_details_capacity_(0),
  60. send_status_(nullptr),
  61. trailing_metadata_count_(0),
  62. trailing_metadata_(nullptr),
  63. cancelled_buf_(0),
  64. recv_closed_(nullptr) {}
  65. void CallOpBuffer::Reset(void* next_return_tag) {
  66. return_tag_ = next_return_tag;
  67. send_initial_metadata_ = false;
  68. initial_metadata_count_ = 0;
  69. gpr_free(initial_metadata_);
  70. recv_initial_metadata_ = nullptr;
  71. recv_initial_metadata_arr_.count = 0;
  72. if (send_buf_ && send_message_) {
  73. grpc_byte_buffer_destroy(send_buf_);
  74. }
  75. send_message_ = nullptr;
  76. send_message_buffer_ = nullptr;
  77. send_buf_ = nullptr;
  78. got_message = false;
  79. if (recv_buf_ && recv_message_) {
  80. grpc_byte_buffer_destroy(recv_buf_);
  81. }
  82. recv_message_ = nullptr;
  83. recv_message_buffer_ = nullptr;
  84. recv_buf_ = nullptr;
  85. client_send_close_ = false;
  86. recv_trailing_metadata_ = nullptr;
  87. recv_status_ = nullptr;
  88. recv_trailing_metadata_arr_.count = 0;
  89. status_code_ = GRPC_STATUS_OK;
  90. send_status_ = nullptr;
  91. trailing_metadata_count_ = 0;
  92. trailing_metadata_ = nullptr;
  93. recv_closed_ = nullptr;
  94. }
  95. CallOpBuffer::~CallOpBuffer() {
  96. gpr_free(status_details_);
  97. gpr_free(recv_initial_metadata_arr_.metadata);
  98. gpr_free(recv_trailing_metadata_arr_.metadata);
  99. if (recv_buf_ && recv_message_) {
  100. grpc_byte_buffer_destroy(recv_buf_);
  101. }
  102. if (send_buf_ && send_message_) {
  103. grpc_byte_buffer_destroy(send_buf_);
  104. }
  105. }
  106. namespace {
  107. // TODO(yangg) if the map is changed before we send, the pointers will be a
  108. // mess. Make sure it does not happen.
  109. grpc_metadata* FillMetadataArray(
  110. std::multimap<grpc::string, grpc::string>* metadata) {
  111. if (metadata->empty()) {
  112. return nullptr;
  113. }
  114. grpc_metadata* metadata_array =
  115. (grpc_metadata*)gpr_malloc(metadata->size() * sizeof(grpc_metadata));
  116. size_t i = 0;
  117. for (auto iter = metadata->cbegin(); iter != metadata->cend(); ++iter, ++i) {
  118. metadata_array[i].key = iter->first.c_str();
  119. metadata_array[i].value = iter->second.c_str();
  120. metadata_array[i].value_length = iter->second.size();
  121. }
  122. return metadata_array;
  123. }
  124. void FillMetadataMap(grpc_metadata_array* arr,
  125. std::multimap<grpc::string, grpc::string>* metadata) {
  126. for (size_t i = 0; i < arr->count; i++) {
  127. // TODO(yangg) handle duplicates?
  128. metadata->insert(std::pair<grpc::string, grpc::string>(
  129. arr->metadata[i].key,
  130. {arr->metadata[i].value, arr->metadata[i].value_length}));
  131. }
  132. grpc_metadata_array_destroy(arr);
  133. grpc_metadata_array_init(arr);
  134. }
  135. } // namespace
  136. void CallOpBuffer::AddSendInitialMetadata(
  137. std::multimap<grpc::string, grpc::string>* metadata) {
  138. send_initial_metadata_ = true;
  139. initial_metadata_count_ = metadata->size();
  140. initial_metadata_ = FillMetadataArray(metadata);
  141. }
  142. void CallOpBuffer::AddRecvInitialMetadata(ClientContext* ctx) {
  143. ctx->initial_metadata_received_ = true;
  144. recv_initial_metadata_ = &ctx->recv_initial_metadata_;
  145. }
  146. void CallOpBuffer::AddSendInitialMetadata(ClientContext* ctx) {
  147. AddSendInitialMetadata(&ctx->send_initial_metadata_);
  148. }
  149. void CallOpBuffer::AddSendMessage(const grpc::protobuf::Message& message) {
  150. send_message_ = &message;
  151. }
  152. void CallOpBuffer::AddSendMessage(const ByteBuffer& message) {
  153. send_message_buffer_ = &message;
  154. }
  155. void CallOpBuffer::AddRecvMessage(grpc::protobuf::Message* message) {
  156. recv_message_ = message;
  157. recv_message_->Clear();
  158. }
  159. void CallOpBuffer::AddRecvMessage(ByteBuffer* message) {
  160. recv_message_buffer_ = message;
  161. }
  162. void CallOpBuffer::AddClientSendClose() { client_send_close_ = true; }
  163. void CallOpBuffer::AddServerRecvClose(bool* cancelled) {
  164. recv_closed_ = cancelled;
  165. }
  166. void CallOpBuffer::AddClientRecvStatus(ClientContext* context, Status* status) {
  167. recv_trailing_metadata_ = &context->trailing_metadata_;
  168. recv_status_ = status;
  169. }
  170. void CallOpBuffer::AddServerSendStatus(
  171. std::multimap<grpc::string, grpc::string>* metadata, const Status& status) {
  172. if (metadata != NULL) {
  173. trailing_metadata_count_ = metadata->size();
  174. trailing_metadata_ = FillMetadataArray(metadata);
  175. } else {
  176. trailing_metadata_count_ = 0;
  177. }
  178. send_status_ = &status;
  179. }
  180. void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
  181. *nops = 0;
  182. if (send_initial_metadata_) {
  183. ops[*nops].op = GRPC_OP_SEND_INITIAL_METADATA;
  184. ops[*nops].data.send_initial_metadata.count = initial_metadata_count_;
  185. ops[*nops].data.send_initial_metadata.metadata = initial_metadata_;
  186. (*nops)++;
  187. }
  188. if (recv_initial_metadata_) {
  189. ops[*nops].op = GRPC_OP_RECV_INITIAL_METADATA;
  190. ops[*nops].data.recv_initial_metadata = &recv_initial_metadata_arr_;
  191. (*nops)++;
  192. }
  193. if (send_message_ || send_message_buffer_) {
  194. if (send_message_) {
  195. bool success = SerializeProto(*send_message_, &send_buf_);
  196. if (!success) {
  197. abort();
  198. // TODO handle parse failure
  199. }
  200. } else {
  201. send_buf_ = send_message_buffer_->buffer();
  202. }
  203. ops[*nops].op = GRPC_OP_SEND_MESSAGE;
  204. ops[*nops].data.send_message = send_buf_;
  205. (*nops)++;
  206. }
  207. if (recv_message_ || recv_message_buffer_) {
  208. ops[*nops].op = GRPC_OP_RECV_MESSAGE;
  209. ops[*nops].data.recv_message = &recv_buf_;
  210. (*nops)++;
  211. }
  212. if (client_send_close_) {
  213. ops[*nops].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  214. (*nops)++;
  215. }
  216. if (recv_status_) {
  217. ops[*nops].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  218. ops[*nops].data.recv_status_on_client.trailing_metadata =
  219. &recv_trailing_metadata_arr_;
  220. ops[*nops].data.recv_status_on_client.status = &status_code_;
  221. ops[*nops].data.recv_status_on_client.status_details = &status_details_;
  222. ops[*nops].data.recv_status_on_client.status_details_capacity =
  223. &status_details_capacity_;
  224. (*nops)++;
  225. }
  226. if (send_status_) {
  227. ops[*nops].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
  228. ops[*nops].data.send_status_from_server.trailing_metadata_count =
  229. trailing_metadata_count_;
  230. ops[*nops].data.send_status_from_server.trailing_metadata =
  231. trailing_metadata_;
  232. ops[*nops].data.send_status_from_server.status =
  233. static_cast<grpc_status_code>(send_status_->code());
  234. ops[*nops].data.send_status_from_server.status_details =
  235. send_status_->details().c_str();
  236. (*nops)++;
  237. }
  238. if (recv_closed_) {
  239. ops[*nops].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
  240. ops[*nops].data.recv_close_on_server.cancelled = &cancelled_buf_;
  241. (*nops)++;
  242. }
  243. }
  244. bool CallOpBuffer::FinalizeResult(void** tag, bool* status) {
  245. // Release send buffers.
  246. if (send_buf_ && send_message_) {
  247. if (send_message_) {
  248. grpc_byte_buffer_destroy(send_buf_);
  249. }
  250. send_buf_ = nullptr;
  251. }
  252. if (initial_metadata_) {
  253. gpr_free(initial_metadata_);
  254. initial_metadata_ = nullptr;
  255. }
  256. if (trailing_metadata_count_) {
  257. gpr_free(trailing_metadata_);
  258. trailing_metadata_ = nullptr;
  259. }
  260. // Set user-facing tag.
  261. *tag = return_tag_;
  262. // Process received initial metadata
  263. if (recv_initial_metadata_) {
  264. FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
  265. }
  266. // Parse received message if any.
  267. if (recv_message_ || recv_message_buffer_) {
  268. if (recv_buf_) {
  269. got_message = *status;
  270. if (recv_message_) {
  271. *status = *status && DeserializeProto(recv_buf_, recv_message_);
  272. grpc_byte_buffer_destroy(recv_buf_);
  273. } else {
  274. recv_message_buffer_->set_buffer(recv_buf_);
  275. }
  276. recv_buf_ = nullptr;
  277. } else {
  278. // Read failed
  279. got_message = false;
  280. *status = false;
  281. }
  282. }
  283. // Parse received status.
  284. if (recv_status_) {
  285. FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
  286. *recv_status_ = Status(
  287. static_cast<StatusCode>(status_code_),
  288. status_details_ ? grpc::string(status_details_) : grpc::string());
  289. }
  290. if (recv_closed_) {
  291. *recv_closed_ = cancelled_buf_ != 0;
  292. }
  293. return true;
  294. }
  295. Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
  296. : call_hook_(call_hook), cq_(cq), call_(call) {}
  297. void Call::PerformOps(CallOpBuffer* buffer) {
  298. call_hook_->PerformOpsOnCall(buffer, this);
  299. }
  300. } // namespace grpc