server_context.cc 12 KB

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