server_context.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include <grpcpp/server_context.h>
  19. #include <grpcpp/support/server_callback.h>
  20. #include <algorithm>
  21. #include <mutex>
  22. #include <utility>
  23. #include <grpc/compression.h>
  24. #include <grpc/grpc.h>
  25. #include <grpc/load_reporting.h>
  26. #include <grpc/support/alloc.h>
  27. #include <grpc/support/log.h>
  28. #include <grpcpp/completion_queue.h>
  29. #include <grpcpp/impl/call.h>
  30. #include <grpcpp/support/time.h>
  31. #include "src/core/lib/surface/call.h"
  32. namespace grpc {
  33. // CompletionOp
  34. class ServerContext::CompletionOp final : public internal::CallOpSetInterface {
  35. public:
  36. // initial refs: one in the server context, one in the cq
  37. // must ref the call before calling constructor and after deleting this
  38. CompletionOp(internal::Call* call, internal::ServerReactor* reactor)
  39. : call_(*call),
  40. reactor_(reactor),
  41. has_tag_(false),
  42. tag_(nullptr),
  43. core_cq_tag_(this),
  44. refs_(2),
  45. finalized_(false),
  46. cancelled_(0),
  47. done_intercepting_(false) {}
  48. // CompletionOp isn't copyable or movable
  49. CompletionOp(const CompletionOp&) = delete;
  50. CompletionOp& operator=(const CompletionOp&) = delete;
  51. CompletionOp(CompletionOp&&) = delete;
  52. CompletionOp& operator=(CompletionOp&&) = delete;
  53. ~CompletionOp() {
  54. if (call_.server_rpc_info()) {
  55. call_.server_rpc_info()->Unref();
  56. }
  57. }
  58. void FillOps(internal::Call* call) override;
  59. // This should always be arena allocated in the call, so override delete.
  60. // But this class is not trivially destructible, so must actually call delete
  61. // before allowing the arena to be freed
  62. static void operator delete(void* ptr, std::size_t size) {
  63. assert(size == sizeof(CompletionOp));
  64. }
  65. // This operator should never be called as the memory should be freed as part
  66. // of the arena destruction. It only exists to provide a matching operator
  67. // delete to the operator new so that some compilers will not complain (see
  68. // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
  69. // there are no tests catching the compiler warning.
  70. static void operator delete(void*, void*) { assert(0); }
  71. bool FinalizeResult(void** tag, bool* status) override;
  72. bool CheckCancelled(CompletionQueue* cq) {
  73. cq->TryPluck(this);
  74. return CheckCancelledNoPluck();
  75. }
  76. bool CheckCancelledAsync() { return CheckCancelledNoPluck(); }
  77. void set_tag(void* tag) {
  78. has_tag_ = true;
  79. tag_ = tag;
  80. }
  81. void set_core_cq_tag(void* core_cq_tag) { core_cq_tag_ = core_cq_tag; }
  82. void* core_cq_tag() override { return core_cq_tag_; }
  83. void Unref();
  84. // This will be called while interceptors are run if the RPC is a hijacked
  85. // RPC. This should set hijacking state for each of the ops.
  86. void SetHijackingState() override {
  87. /* Servers don't allow hijacking */
  88. GPR_CODEGEN_ASSERT(false);
  89. }
  90. /* Should be called after interceptors are done running */
  91. void ContinueFillOpsAfterInterception() override {}
  92. /* Should be called after interceptors are done running on the finalize result
  93. * path */
  94. void ContinueFinalizeResultAfterInterception() override {
  95. done_intercepting_ = true;
  96. if (!has_tag_) {
  97. /* We don't have a tag to return. */
  98. std::unique_lock<std::mutex> lock(mu_);
  99. if (--refs_ == 0) {
  100. lock.unlock();
  101. grpc_call* call = call_.call();
  102. delete this;
  103. grpc_call_unref(call);
  104. }
  105. return;
  106. }
  107. /* Start a dummy op so that we can return the tag */
  108. GPR_CODEGEN_ASSERT(
  109. GRPC_CALL_OK ==
  110. grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag_, nullptr));
  111. }
  112. private:
  113. bool CheckCancelledNoPluck() {
  114. std::lock_guard<std::mutex> g(mu_);
  115. return finalized_ ? (cancelled_ != 0) : false;
  116. }
  117. internal::Call call_;
  118. internal::ServerReactor* reactor_;
  119. bool has_tag_;
  120. void* tag_;
  121. void* core_cq_tag_;
  122. std::mutex mu_;
  123. int refs_;
  124. bool finalized_;
  125. int cancelled_; // This is an int (not bool) because it is passed to core
  126. bool done_intercepting_;
  127. internal::InterceptorBatchMethodsImpl interceptor_methods_;
  128. };
  129. void ServerContext::CompletionOp::Unref() {
  130. std::unique_lock<std::mutex> lock(mu_);
  131. if (--refs_ == 0) {
  132. lock.unlock();
  133. grpc_call* call = call_.call();
  134. delete this;
  135. grpc_call_unref(call);
  136. }
  137. }
  138. void ServerContext::CompletionOp::FillOps(internal::Call* call) {
  139. grpc_op ops;
  140. ops.op = GRPC_OP_RECV_CLOSE_ON_SERVER;
  141. ops.data.recv_close_on_server.cancelled = &cancelled_;
  142. ops.flags = 0;
  143. ops.reserved = nullptr;
  144. interceptor_methods_.SetCall(&call_);
  145. interceptor_methods_.SetReverse();
  146. interceptor_methods_.SetCallOpSetInterface(this);
  147. GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call->call(), &ops, 1,
  148. core_cq_tag_, nullptr));
  149. /* No interceptors to run here */
  150. }
  151. bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) {
  152. bool ret = false;
  153. std::unique_lock<std::mutex> lock(mu_);
  154. if (done_intercepting_) {
  155. /* We are done intercepting. */
  156. if (has_tag_) {
  157. *tag = tag_;
  158. ret = true;
  159. }
  160. if (--refs_ == 0) {
  161. lock.unlock();
  162. grpc_call* call = call_.call();
  163. delete this;
  164. grpc_call_unref(call);
  165. }
  166. return ret;
  167. }
  168. finalized_ = true;
  169. // If for some reason the incoming status is false, mark that as a
  170. // cancellation.
  171. // TODO(vjpai): does this ever happen?
  172. if (!*status) {
  173. cancelled_ = 1;
  174. }
  175. if (cancelled_ && (reactor_ != nullptr)) {
  176. reactor_->OnCancel();
  177. }
  178. /* Release the lock since we are going to be running through interceptors now
  179. */
  180. lock.unlock();
  181. /* Add interception point and run through interceptors */
  182. interceptor_methods_.AddInterceptionHookPoint(
  183. experimental::InterceptionHookPoints::POST_RECV_CLOSE);
  184. if (interceptor_methods_.RunInterceptors()) {
  185. /* No interceptors were run */
  186. if (has_tag_) {
  187. *tag = tag_;
  188. ret = true;
  189. }
  190. lock.lock();
  191. if (--refs_ == 0) {
  192. lock.unlock();
  193. grpc_call* call = call_.call();
  194. delete this;
  195. grpc_call_unref(call);
  196. }
  197. return ret;
  198. }
  199. /* There are interceptors to be run. Return false for now */
  200. return false;
  201. }
  202. // ServerContext body
  203. ServerContext::ServerContext() { Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); }
  204. ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata_array* arr) {
  205. Setup(deadline);
  206. std::swap(*client_metadata_.arr(), *arr);
  207. }
  208. void ServerContext::Setup(gpr_timespec deadline) {
  209. completion_op_ = nullptr;
  210. has_notify_when_done_tag_ = false;
  211. async_notify_when_done_tag_ = nullptr;
  212. deadline_ = deadline;
  213. call_ = nullptr;
  214. cq_ = nullptr;
  215. sent_initial_metadata_ = false;
  216. compression_level_set_ = false;
  217. has_pending_ops_ = false;
  218. rpc_info_ = nullptr;
  219. }
  220. void ServerContext::BindDeadlineAndMetadata(gpr_timespec deadline,
  221. grpc_metadata_array* arr) {
  222. deadline_ = deadline;
  223. std::swap(*client_metadata_.arr(), *arr);
  224. }
  225. ServerContext::~ServerContext() { Clear(); }
  226. void ServerContext::Clear() {
  227. auth_context_.reset();
  228. initial_metadata_.clear();
  229. trailing_metadata_.clear();
  230. client_metadata_.Reset();
  231. if (completion_op_) {
  232. completion_op_->Unref();
  233. completion_op_ = nullptr;
  234. completion_tag_.Clear();
  235. }
  236. if (rpc_info_) {
  237. rpc_info_->Unref();
  238. rpc_info_ = nullptr;
  239. }
  240. if (call_) {
  241. auto* call = call_;
  242. call_ = nullptr;
  243. grpc_call_unref(call);
  244. }
  245. }
  246. void ServerContext::BeginCompletionOp(internal::Call* call,
  247. std::function<void(bool)> callback,
  248. internal::ServerReactor* reactor) {
  249. GPR_ASSERT(!completion_op_);
  250. if (rpc_info_) {
  251. rpc_info_->Ref();
  252. }
  253. grpc_call_ref(call->call());
  254. completion_op_ =
  255. new (grpc_call_arena_alloc(call->call(), sizeof(CompletionOp)))
  256. CompletionOp(call, reactor);
  257. if (callback != nullptr) {
  258. completion_tag_.Set(call->call(), std::move(callback), completion_op_);
  259. completion_op_->set_core_cq_tag(&completion_tag_);
  260. completion_op_->set_tag(completion_op_);
  261. } else if (has_notify_when_done_tag_) {
  262. completion_op_->set_tag(async_notify_when_done_tag_);
  263. }
  264. call->PerformOps(completion_op_);
  265. }
  266. internal::CompletionQueueTag* ServerContext::GetCompletionOpTag() {
  267. return static_cast<internal::CompletionQueueTag*>(completion_op_);
  268. }
  269. void ServerContext::AddInitialMetadata(const grpc::string& key,
  270. const grpc::string& value) {
  271. initial_metadata_.insert(std::make_pair(key, value));
  272. }
  273. void ServerContext::AddTrailingMetadata(const grpc::string& key,
  274. const grpc::string& value) {
  275. trailing_metadata_.insert(std::make_pair(key, value));
  276. }
  277. void ServerContext::TryCancel() const {
  278. internal::CancelInterceptorBatchMethods cancel_methods;
  279. if (rpc_info_) {
  280. for (size_t i = 0; i < rpc_info_->interceptors_.size(); i++) {
  281. rpc_info_->RunInterceptor(&cancel_methods, i);
  282. }
  283. }
  284. grpc_call_error err = grpc_call_cancel_with_status(
  285. call_, GRPC_STATUS_CANCELLED, "Cancelled on the server side", nullptr);
  286. if (err != GRPC_CALL_OK) {
  287. gpr_log(GPR_ERROR, "TryCancel failed with: %d", err);
  288. }
  289. }
  290. bool ServerContext::IsCancelled() const {
  291. if (completion_tag_) {
  292. // When using callback API, this result is always valid.
  293. return completion_op_->CheckCancelledAsync();
  294. } else if (has_notify_when_done_tag_) {
  295. // When using async API, the result is only valid
  296. // if the tag has already been delivered at the completion queue
  297. return completion_op_ && completion_op_->CheckCancelledAsync();
  298. } else {
  299. // when using sync API, the result is always valid
  300. return completion_op_ && completion_op_->CheckCancelled(cq_);
  301. }
  302. }
  303. void ServerContext::set_compression_algorithm(
  304. grpc_compression_algorithm algorithm) {
  305. compression_algorithm_ = algorithm;
  306. const char* algorithm_name = nullptr;
  307. if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) {
  308. gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.",
  309. algorithm);
  310. abort();
  311. }
  312. GPR_ASSERT(algorithm_name != nullptr);
  313. AddInitialMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name);
  314. }
  315. grpc::string ServerContext::peer() const {
  316. grpc::string peer;
  317. if (call_) {
  318. char* c_peer = grpc_call_get_peer(call_);
  319. peer = c_peer;
  320. gpr_free(c_peer);
  321. }
  322. return peer;
  323. }
  324. const struct census_context* ServerContext::census_context() const {
  325. return grpc_census_call_get_context(call_);
  326. }
  327. void ServerContext::SetLoadReportingCosts(
  328. const std::vector<grpc::string>& cost_data) {
  329. if (call_ == nullptr) return;
  330. for (const auto& cost_datum : cost_data) {
  331. AddTrailingMetadata(GRPC_LB_COST_MD_KEY, cost_datum);
  332. }
  333. }
  334. } // namespace grpc