server_context.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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/impl/codegen/server_context.h>
  19. #include <algorithm>
  20. #include <utility>
  21. #include <grpc/compression.h>
  22. #include <grpc/grpc.h>
  23. #include <grpc/load_reporting.h>
  24. #include <grpc/support/alloc.h>
  25. #include <grpc/support/log.h>
  26. #include <grpcpp/impl/call.h>
  27. #include <grpcpp/impl/codegen/completion_queue.h>
  28. #include <grpcpp/support/server_callback.h>
  29. #include <grpcpp/support/time.h>
  30. #include "src/core/lib/gprpp/ref_counted.h"
  31. #include "src/core/lib/gprpp/sync.h"
  32. #include "src/core/lib/surface/call.h"
  33. namespace grpc {
  34. // CompletionOp
  35. class ServerContextBase::CompletionOp final
  36. : public internal::CallOpSetInterface {
  37. public:
  38. // initial refs: one in the server context, one in the cq
  39. // must ref the call before calling constructor and after deleting this
  40. CompletionOp(internal::Call* call,
  41. ::grpc::internal::ServerCallbackCall* callback_controller)
  42. : call_(*call),
  43. callback_controller_(callback_controller),
  44. has_tag_(false),
  45. tag_(nullptr),
  46. core_cq_tag_(this),
  47. refs_(2),
  48. finalized_(false),
  49. cancelled_(0),
  50. done_intercepting_(false) {}
  51. // CompletionOp isn't copyable or movable
  52. CompletionOp(const CompletionOp&) = delete;
  53. CompletionOp& operator=(const CompletionOp&) = delete;
  54. CompletionOp(CompletionOp&&) = delete;
  55. CompletionOp& operator=(CompletionOp&&) = delete;
  56. ~CompletionOp() override {
  57. if (call_.server_rpc_info()) {
  58. call_.server_rpc_info()->Unref();
  59. }
  60. }
  61. void FillOps(internal::Call* call) override;
  62. // This should always be arena allocated in the call, so override delete.
  63. // But this class is not trivially destructible, so must actually call delete
  64. // before allowing the arena to be freed
  65. static void operator delete(void* /*ptr*/, std::size_t size) {
  66. // Use size to avoid unused-parameter warning since assert seems to be
  67. // compiled out and treated as unused in some gcc optimized versions.
  68. (void)size;
  69. assert(size == sizeof(CompletionOp));
  70. }
  71. // This operator should never be called as the memory should be freed as part
  72. // of the arena destruction. It only exists to provide a matching operator
  73. // delete to the operator new so that some compilers will not complain (see
  74. // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
  75. // there are no tests catching the compiler warning.
  76. static void operator delete(void*, void*) { assert(0); }
  77. bool FinalizeResult(void** tag, bool* status) override;
  78. bool CheckCancelled(CompletionQueue* cq) {
  79. cq->TryPluck(this);
  80. return CheckCancelledNoPluck();
  81. }
  82. bool CheckCancelledAsync() { return CheckCancelledNoPluck(); }
  83. void set_tag(void* tag) {
  84. has_tag_ = true;
  85. tag_ = tag;
  86. }
  87. void set_core_cq_tag(void* core_cq_tag) { core_cq_tag_ = core_cq_tag; }
  88. void* core_cq_tag() override { return core_cq_tag_; }
  89. void Unref();
  90. // This will be called while interceptors are run if the RPC is a hijacked
  91. // RPC. This should set hijacking state for each of the ops.
  92. void SetHijackingState() override {
  93. /* Servers don't allow hijacking */
  94. GPR_ASSERT(false);
  95. }
  96. /* Should be called after interceptors are done running */
  97. void ContinueFillOpsAfterInterception() override {}
  98. /* Should be called after interceptors are done running on the finalize result
  99. * path */
  100. void ContinueFinalizeResultAfterInterception() override {
  101. done_intercepting_ = true;
  102. if (!has_tag_) {
  103. // We don't have a tag to return.
  104. Unref();
  105. // Unref can delete this, so do not access anything from this afterward.
  106. return;
  107. }
  108. /* Start a dummy op so that we can return the tag */
  109. GPR_ASSERT(grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag_,
  110. nullptr) == GRPC_CALL_OK);
  111. }
  112. private:
  113. bool CheckCancelledNoPluck() {
  114. grpc_core::MutexLock lock(&mu_);
  115. return finalized_ ? (cancelled_ != 0) : false;
  116. }
  117. internal::Call call_;
  118. ::grpc::internal::ServerCallbackCall* const callback_controller_;
  119. bool has_tag_;
  120. void* tag_;
  121. void* core_cq_tag_;
  122. grpc_core::RefCount refs_;
  123. grpc_core::Mutex mu_;
  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 ServerContextBase::CompletionOp::Unref() {
  130. if (refs_.Unref()) {
  131. grpc_call* call = call_.call();
  132. delete this;
  133. grpc_call_unref(call);
  134. }
  135. }
  136. void ServerContextBase::CompletionOp::FillOps(internal::Call* call) {
  137. grpc_op ops;
  138. ops.op = GRPC_OP_RECV_CLOSE_ON_SERVER;
  139. ops.data.recv_close_on_server.cancelled = &cancelled_;
  140. ops.flags = 0;
  141. ops.reserved = nullptr;
  142. interceptor_methods_.SetCall(&call_);
  143. interceptor_methods_.SetReverse();
  144. interceptor_methods_.SetCallOpSetInterface(this);
  145. // The following call_start_batch is internally-generated so no need for an
  146. // explanatory log on failure.
  147. GPR_ASSERT(grpc_call_start_batch(call->call(), &ops, 1, core_cq_tag_,
  148. nullptr) == GRPC_CALL_OK);
  149. /* No interceptors to run here */
  150. }
  151. bool ServerContextBase::CompletionOp::FinalizeResult(void** tag, bool* status) {
  152. // Decide whether to do the unref or call the cancel callback within the lock
  153. bool do_unref = false;
  154. bool has_tag = false;
  155. bool call_cancel = false;
  156. {
  157. grpc_core::MutexLock lock(&mu_);
  158. if (done_intercepting_) {
  159. // We are done intercepting.
  160. has_tag = has_tag_;
  161. if (has_tag) {
  162. *tag = tag_;
  163. }
  164. // Release the lock before unreffing as Unref may delete this object
  165. do_unref = true;
  166. } else {
  167. finalized_ = true;
  168. // If for some reason the incoming status is false, mark that as a
  169. // cancellation.
  170. // TODO(vjpai): does this ever happen?
  171. if (!*status) {
  172. cancelled_ = 1;
  173. }
  174. call_cancel = (cancelled_ != 0);
  175. // Release the lock since we may call a callback and interceptors.
  176. }
  177. }
  178. if (do_unref) {
  179. Unref();
  180. // Unref can delete this, so do not access anything from this afterward.
  181. return has_tag;
  182. }
  183. if (call_cancel && callback_controller_ != nullptr) {
  184. callback_controller_->MaybeCallOnCancel();
  185. }
  186. /* Add interception point and run through interceptors */
  187. interceptor_methods_.AddInterceptionHookPoint(
  188. experimental::InterceptionHookPoints::POST_RECV_CLOSE);
  189. if (interceptor_methods_.RunInterceptors()) {
  190. // No interceptors were run
  191. bool has_tag = has_tag_;
  192. if (has_tag) {
  193. *tag = tag_;
  194. }
  195. Unref();
  196. // Unref can delete this, so do not access anything from this afterward.
  197. return has_tag;
  198. }
  199. // There are interceptors to be run. Return false for now.
  200. return false;
  201. }
  202. // ServerContextBase body
  203. ServerContextBase::ServerContextBase()
  204. : deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)) {}
  205. ServerContextBase::ServerContextBase(gpr_timespec deadline,
  206. grpc_metadata_array* arr)
  207. : deadline_(deadline) {
  208. std::swap(*client_metadata_.arr(), *arr);
  209. }
  210. void ServerContextBase::BindDeadlineAndMetadata(gpr_timespec deadline,
  211. grpc_metadata_array* arr) {
  212. deadline_ = deadline;
  213. std::swap(*client_metadata_.arr(), *arr);
  214. }
  215. ServerContextBase::~ServerContextBase() {
  216. if (completion_op_) {
  217. completion_op_->Unref();
  218. // Unref can delete completion_op_, so do not access it afterward.
  219. }
  220. if (rpc_info_) {
  221. rpc_info_->Unref();
  222. }
  223. if (default_reactor_used_.load(std::memory_order_relaxed)) {
  224. reinterpret_cast<Reactor*>(&default_reactor_)->~Reactor();
  225. }
  226. }
  227. ServerContextBase::CallWrapper::~CallWrapper() {
  228. if (call) {
  229. // If the ServerContext is part of the call's arena, this could free the
  230. // object itself.
  231. grpc_call_unref(call);
  232. }
  233. }
  234. void ServerContextBase::BeginCompletionOp(
  235. internal::Call* call, std::function<void(bool)> callback,
  236. ::grpc::internal::ServerCallbackCall* callback_controller) {
  237. GPR_ASSERT(!completion_op_);
  238. if (rpc_info_) {
  239. rpc_info_->Ref();
  240. }
  241. grpc_call_ref(call->call());
  242. completion_op_ =
  243. new (grpc_call_arena_alloc(call->call(), sizeof(CompletionOp)))
  244. CompletionOp(call, callback_controller);
  245. if (callback_controller != nullptr) {
  246. completion_tag_.Set(call->call(), std::move(callback), completion_op_,
  247. true);
  248. completion_op_->set_core_cq_tag(&completion_tag_);
  249. completion_op_->set_tag(completion_op_);
  250. } else if (has_notify_when_done_tag_) {
  251. completion_op_->set_tag(async_notify_when_done_tag_);
  252. }
  253. call->PerformOps(completion_op_);
  254. }
  255. internal::CompletionQueueTag* ServerContextBase::GetCompletionOpTag() {
  256. return static_cast<internal::CompletionQueueTag*>(completion_op_);
  257. }
  258. void ServerContextBase::AddInitialMetadata(const std::string& key,
  259. const std::string& value) {
  260. initial_metadata_.insert(std::make_pair(key, value));
  261. }
  262. void ServerContextBase::AddTrailingMetadata(const std::string& key,
  263. const std::string& value) {
  264. trailing_metadata_.insert(std::make_pair(key, value));
  265. }
  266. void ServerContextBase::TryCancel() const {
  267. internal::CancelInterceptorBatchMethods cancel_methods;
  268. if (rpc_info_) {
  269. for (size_t i = 0; i < rpc_info_->interceptors_.size(); i++) {
  270. rpc_info_->RunInterceptor(&cancel_methods, i);
  271. }
  272. }
  273. grpc_call_error err =
  274. grpc_call_cancel_with_status(call_.call, GRPC_STATUS_CANCELLED,
  275. "Cancelled on the server side", nullptr);
  276. if (err != GRPC_CALL_OK) {
  277. gpr_log(GPR_ERROR, "TryCancel failed with: %d", err);
  278. }
  279. }
  280. bool ServerContextBase::IsCancelled() const {
  281. if (completion_tag_) {
  282. // When using callback API, this result is always valid.
  283. return completion_op_->CheckCancelledAsync();
  284. } else if (has_notify_when_done_tag_) {
  285. // When using async API, the result is only valid
  286. // if the tag has already been delivered at the completion queue
  287. return completion_op_ && completion_op_->CheckCancelledAsync();
  288. } else {
  289. // when using sync API, the result is always valid
  290. return completion_op_ && completion_op_->CheckCancelled(cq_);
  291. }
  292. }
  293. void ServerContextBase::set_compression_algorithm(
  294. grpc_compression_algorithm algorithm) {
  295. compression_algorithm_ = algorithm;
  296. const char* algorithm_name = nullptr;
  297. if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) {
  298. gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.",
  299. algorithm);
  300. abort();
  301. }
  302. GPR_ASSERT(algorithm_name != nullptr);
  303. AddInitialMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name);
  304. }
  305. std::string ServerContextBase::peer() const {
  306. std::string peer;
  307. if (call_.call) {
  308. char* c_peer = grpc_call_get_peer(call_.call);
  309. peer = c_peer;
  310. gpr_free(c_peer);
  311. }
  312. return peer;
  313. }
  314. const struct census_context* ServerContextBase::census_context() const {
  315. return call_.call == nullptr ? nullptr
  316. : grpc_census_call_get_context(call_.call);
  317. }
  318. void ServerContextBase::SetLoadReportingCosts(
  319. const std::vector<std::string>& cost_data) {
  320. if (call_.call == nullptr) return;
  321. for (const auto& cost_datum : cost_data) {
  322. AddTrailingMetadata(GRPC_LB_COST_MD_KEY, cost_datum);
  323. }
  324. }
  325. } // namespace grpc