xref: /aosp_15_r20/external/grpc-grpc/src/cpp/server/server_context.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard Worker //
2*cc02d7e2SAndroid Build Coastguard Worker //
3*cc02d7e2SAndroid Build Coastguard Worker // Copyright 2015 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker //
5*cc02d7e2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker //
9*cc02d7e2SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker //
11*cc02d7e2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker // limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker //
17*cc02d7e2SAndroid Build Coastguard Worker //
18*cc02d7e2SAndroid Build Coastguard Worker 
19*cc02d7e2SAndroid Build Coastguard Worker #include <assert.h>
20*cc02d7e2SAndroid Build Coastguard Worker 
21*cc02d7e2SAndroid Build Coastguard Worker #include <atomic>
22*cc02d7e2SAndroid Build Coastguard Worker #include <cstdlib>
23*cc02d7e2SAndroid Build Coastguard Worker #include <functional>
24*cc02d7e2SAndroid Build Coastguard Worker #include <map>
25*cc02d7e2SAndroid Build Coastguard Worker #include <memory>
26*cc02d7e2SAndroid Build Coastguard Worker #include <new>
27*cc02d7e2SAndroid Build Coastguard Worker #include <string>
28*cc02d7e2SAndroid Build Coastguard Worker #include <utility>
29*cc02d7e2SAndroid Build Coastguard Worker #include <vector>
30*cc02d7e2SAndroid Build Coastguard Worker 
31*cc02d7e2SAndroid Build Coastguard Worker #include "absl/strings/str_format.h"
32*cc02d7e2SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
33*cc02d7e2SAndroid Build Coastguard Worker 
34*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/compression.h>
35*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/grpc.h>
36*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/impl/compression_types.h>
37*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/load_reporting.h>
38*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/status.h>
39*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/alloc.h>
40*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/log.h>
41*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/time.h>
42*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/completion_queue.h>
43*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/ext/call_metric_recorder.h>
44*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/ext/server_metric_recorder.h>
45*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/call.h>
46*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/call_op_set.h>
47*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/call_op_set_interface.h>
48*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/completion_queue_tag.h>
49*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/interceptor_common.h>
50*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/metadata_map.h>
51*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/server_context.h>
52*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/callback_common.h>
53*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/interceptor.h>
54*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/server_callback.h>
55*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/server_interceptor.h>
56*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/string_ref.h>
57*cc02d7e2SAndroid Build Coastguard Worker 
58*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/channel/context.h"
59*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/crash.h"
60*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/ref_counted.h"
61*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/sync.h"
62*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/resource_quota/arena.h"
63*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/surface/call.h"
64*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/server/backend_metric_recorder.h"
65*cc02d7e2SAndroid Build Coastguard Worker 
66*cc02d7e2SAndroid Build Coastguard Worker namespace grpc {
67*cc02d7e2SAndroid Build Coastguard Worker 
68*cc02d7e2SAndroid Build Coastguard Worker // CompletionOp
69*cc02d7e2SAndroid Build Coastguard Worker 
70*cc02d7e2SAndroid Build Coastguard Worker class ServerContextBase::CompletionOp final
71*cc02d7e2SAndroid Build Coastguard Worker     : public internal::CallOpSetInterface {
72*cc02d7e2SAndroid Build Coastguard Worker  public:
73*cc02d7e2SAndroid Build Coastguard Worker   // initial refs: one in the server context, one in the cq
74*cc02d7e2SAndroid Build Coastguard Worker   // must ref the call before calling constructor and after deleting this
CompletionOp(internal::Call * call,grpc::internal::ServerCallbackCall * callback_controller)75*cc02d7e2SAndroid Build Coastguard Worker   CompletionOp(internal::Call* call,
76*cc02d7e2SAndroid Build Coastguard Worker                grpc::internal::ServerCallbackCall* callback_controller)
77*cc02d7e2SAndroid Build Coastguard Worker       : call_(*call),
78*cc02d7e2SAndroid Build Coastguard Worker         callback_controller_(callback_controller),
79*cc02d7e2SAndroid Build Coastguard Worker         has_tag_(false),
80*cc02d7e2SAndroid Build Coastguard Worker         tag_(nullptr),
81*cc02d7e2SAndroid Build Coastguard Worker         core_cq_tag_(this),
82*cc02d7e2SAndroid Build Coastguard Worker         refs_(2),
83*cc02d7e2SAndroid Build Coastguard Worker         finalized_(false),
84*cc02d7e2SAndroid Build Coastguard Worker         cancelled_(0),
85*cc02d7e2SAndroid Build Coastguard Worker         done_intercepting_(false) {}
86*cc02d7e2SAndroid Build Coastguard Worker 
87*cc02d7e2SAndroid Build Coastguard Worker   // CompletionOp isn't copyable or movable
88*cc02d7e2SAndroid Build Coastguard Worker   CompletionOp(const CompletionOp&) = delete;
89*cc02d7e2SAndroid Build Coastguard Worker   CompletionOp& operator=(const CompletionOp&) = delete;
90*cc02d7e2SAndroid Build Coastguard Worker   CompletionOp(CompletionOp&&) = delete;
91*cc02d7e2SAndroid Build Coastguard Worker   CompletionOp& operator=(CompletionOp&&) = delete;
92*cc02d7e2SAndroid Build Coastguard Worker 
~CompletionOp()93*cc02d7e2SAndroid Build Coastguard Worker   ~CompletionOp() override {
94*cc02d7e2SAndroid Build Coastguard Worker     if (call_.server_rpc_info()) {
95*cc02d7e2SAndroid Build Coastguard Worker       call_.server_rpc_info()->Unref();
96*cc02d7e2SAndroid Build Coastguard Worker     }
97*cc02d7e2SAndroid Build Coastguard Worker   }
98*cc02d7e2SAndroid Build Coastguard Worker 
99*cc02d7e2SAndroid Build Coastguard Worker   void FillOps(internal::Call* call) override;
100*cc02d7e2SAndroid Build Coastguard Worker 
101*cc02d7e2SAndroid Build Coastguard Worker   // This should always be arena allocated in the call, so override delete.
102*cc02d7e2SAndroid Build Coastguard Worker   // But this class is not trivially destructible, so must actually call delete
103*cc02d7e2SAndroid Build Coastguard Worker   // before allowing the arena to be freed
operator delete(void *,std::size_t size)104*cc02d7e2SAndroid Build Coastguard Worker   static void operator delete(void* /*ptr*/, std::size_t size) {
105*cc02d7e2SAndroid Build Coastguard Worker     // Use size to avoid unused-parameter warning since assert seems to be
106*cc02d7e2SAndroid Build Coastguard Worker     // compiled out and treated as unused in some gcc optimized versions.
107*cc02d7e2SAndroid Build Coastguard Worker     (void)size;
108*cc02d7e2SAndroid Build Coastguard Worker     assert(size == sizeof(CompletionOp));
109*cc02d7e2SAndroid Build Coastguard Worker   }
110*cc02d7e2SAndroid Build Coastguard Worker 
111*cc02d7e2SAndroid Build Coastguard Worker   // This operator should never be called as the memory should be freed as part
112*cc02d7e2SAndroid Build Coastguard Worker   // of the arena destruction. It only exists to provide a matching operator
113*cc02d7e2SAndroid Build Coastguard Worker   // delete to the operator new so that some compilers will not complain (see
114*cc02d7e2SAndroid Build Coastguard Worker   // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
115*cc02d7e2SAndroid Build Coastguard Worker   // there are no tests catching the compiler warning.
operator delete(void *,void *)116*cc02d7e2SAndroid Build Coastguard Worker   static void operator delete(void*, void*) { assert(0); }
117*cc02d7e2SAndroid Build Coastguard Worker 
118*cc02d7e2SAndroid Build Coastguard Worker   bool FinalizeResult(void** tag, bool* status) override;
119*cc02d7e2SAndroid Build Coastguard Worker 
CheckCancelled(CompletionQueue * cq)120*cc02d7e2SAndroid Build Coastguard Worker   bool CheckCancelled(CompletionQueue* cq) {
121*cc02d7e2SAndroid Build Coastguard Worker     cq->TryPluck(this);
122*cc02d7e2SAndroid Build Coastguard Worker     return CheckCancelledNoPluck();
123*cc02d7e2SAndroid Build Coastguard Worker   }
CheckCancelledAsync()124*cc02d7e2SAndroid Build Coastguard Worker   bool CheckCancelledAsync() { return CheckCancelledNoPluck(); }
125*cc02d7e2SAndroid Build Coastguard Worker 
set_tag(void * tag)126*cc02d7e2SAndroid Build Coastguard Worker   void set_tag(void* tag) {
127*cc02d7e2SAndroid Build Coastguard Worker     has_tag_ = true;
128*cc02d7e2SAndroid Build Coastguard Worker     tag_ = tag;
129*cc02d7e2SAndroid Build Coastguard Worker   }
130*cc02d7e2SAndroid Build Coastguard Worker 
set_core_cq_tag(void * core_cq_tag)131*cc02d7e2SAndroid Build Coastguard Worker   void set_core_cq_tag(void* core_cq_tag) { core_cq_tag_ = core_cq_tag; }
132*cc02d7e2SAndroid Build Coastguard Worker 
core_cq_tag()133*cc02d7e2SAndroid Build Coastguard Worker   void* core_cq_tag() override { return core_cq_tag_; }
134*cc02d7e2SAndroid Build Coastguard Worker 
135*cc02d7e2SAndroid Build Coastguard Worker   void Unref();
136*cc02d7e2SAndroid Build Coastguard Worker 
137*cc02d7e2SAndroid Build Coastguard Worker   // This will be called while interceptors are run if the RPC is a hijacked
138*cc02d7e2SAndroid Build Coastguard Worker   // RPC. This should set hijacking state for each of the ops.
SetHijackingState()139*cc02d7e2SAndroid Build Coastguard Worker   void SetHijackingState() override {
140*cc02d7e2SAndroid Build Coastguard Worker     // Servers don't allow hijacking
141*cc02d7e2SAndroid Build Coastguard Worker     grpc_core::Crash("unreachable");
142*cc02d7e2SAndroid Build Coastguard Worker   }
143*cc02d7e2SAndroid Build Coastguard Worker 
144*cc02d7e2SAndroid Build Coastguard Worker   // Should be called after interceptors are done running
ContinueFillOpsAfterInterception()145*cc02d7e2SAndroid Build Coastguard Worker   void ContinueFillOpsAfterInterception() override {}
146*cc02d7e2SAndroid Build Coastguard Worker 
147*cc02d7e2SAndroid Build Coastguard Worker   // Should be called after interceptors are done running on the finalize result
148*cc02d7e2SAndroid Build Coastguard Worker   // path
ContinueFinalizeResultAfterInterception()149*cc02d7e2SAndroid Build Coastguard Worker   void ContinueFinalizeResultAfterInterception() override {
150*cc02d7e2SAndroid Build Coastguard Worker     done_intercepting_ = true;
151*cc02d7e2SAndroid Build Coastguard Worker     if (!has_tag_) {
152*cc02d7e2SAndroid Build Coastguard Worker       // We don't have a tag to return.
153*cc02d7e2SAndroid Build Coastguard Worker       Unref();
154*cc02d7e2SAndroid Build Coastguard Worker       // Unref can delete this, so do not access anything from this afterward.
155*cc02d7e2SAndroid Build Coastguard Worker       return;
156*cc02d7e2SAndroid Build Coastguard Worker     }
157*cc02d7e2SAndroid Build Coastguard Worker     // Start a phony op so that we can return the tag
158*cc02d7e2SAndroid Build Coastguard Worker     GPR_ASSERT(grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag_,
159*cc02d7e2SAndroid Build Coastguard Worker                                      nullptr) == GRPC_CALL_OK);
160*cc02d7e2SAndroid Build Coastguard Worker   }
161*cc02d7e2SAndroid Build Coastguard Worker 
162*cc02d7e2SAndroid Build Coastguard Worker  private:
CheckCancelledNoPluck()163*cc02d7e2SAndroid Build Coastguard Worker   bool CheckCancelledNoPluck() {
164*cc02d7e2SAndroid Build Coastguard Worker     grpc_core::MutexLock lock(&mu_);
165*cc02d7e2SAndroid Build Coastguard Worker     return finalized_ ? (cancelled_ != 0) : false;
166*cc02d7e2SAndroid Build Coastguard Worker   }
167*cc02d7e2SAndroid Build Coastguard Worker 
168*cc02d7e2SAndroid Build Coastguard Worker   internal::Call call_;
169*cc02d7e2SAndroid Build Coastguard Worker   grpc::internal::ServerCallbackCall* const callback_controller_;
170*cc02d7e2SAndroid Build Coastguard Worker   bool has_tag_;
171*cc02d7e2SAndroid Build Coastguard Worker   void* tag_;
172*cc02d7e2SAndroid Build Coastguard Worker   void* core_cq_tag_;
173*cc02d7e2SAndroid Build Coastguard Worker   grpc_core::RefCount refs_;
174*cc02d7e2SAndroid Build Coastguard Worker   grpc_core::Mutex mu_;
175*cc02d7e2SAndroid Build Coastguard Worker   bool finalized_;
176*cc02d7e2SAndroid Build Coastguard Worker   int cancelled_;  // This is an int (not bool) because it is passed to core
177*cc02d7e2SAndroid Build Coastguard Worker   bool done_intercepting_;
178*cc02d7e2SAndroid Build Coastguard Worker   internal::InterceptorBatchMethodsImpl interceptor_methods_;
179*cc02d7e2SAndroid Build Coastguard Worker };
180*cc02d7e2SAndroid Build Coastguard Worker 
Unref()181*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::CompletionOp::Unref() {
182*cc02d7e2SAndroid Build Coastguard Worker   if (refs_.Unref()) {
183*cc02d7e2SAndroid Build Coastguard Worker     grpc_call* call = call_.call();
184*cc02d7e2SAndroid Build Coastguard Worker     delete this;
185*cc02d7e2SAndroid Build Coastguard Worker     grpc_call_unref(call);
186*cc02d7e2SAndroid Build Coastguard Worker   }
187*cc02d7e2SAndroid Build Coastguard Worker }
188*cc02d7e2SAndroid Build Coastguard Worker 
FillOps(internal::Call * call)189*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::CompletionOp::FillOps(internal::Call* call) {
190*cc02d7e2SAndroid Build Coastguard Worker   grpc_op ops;
191*cc02d7e2SAndroid Build Coastguard Worker   ops.op = GRPC_OP_RECV_CLOSE_ON_SERVER;
192*cc02d7e2SAndroid Build Coastguard Worker   ops.data.recv_close_on_server.cancelled = &cancelled_;
193*cc02d7e2SAndroid Build Coastguard Worker   ops.flags = 0;
194*cc02d7e2SAndroid Build Coastguard Worker   ops.reserved = nullptr;
195*cc02d7e2SAndroid Build Coastguard Worker   interceptor_methods_.SetCall(&call_);
196*cc02d7e2SAndroid Build Coastguard Worker   interceptor_methods_.SetReverse();
197*cc02d7e2SAndroid Build Coastguard Worker   interceptor_methods_.SetCallOpSetInterface(this);
198*cc02d7e2SAndroid Build Coastguard Worker   // The following call_start_batch is internally-generated so no need for an
199*cc02d7e2SAndroid Build Coastguard Worker   // explanatory log on failure.
200*cc02d7e2SAndroid Build Coastguard Worker   GPR_ASSERT(grpc_call_start_batch(call->call(), &ops, 1, core_cq_tag_,
201*cc02d7e2SAndroid Build Coastguard Worker                                    nullptr) == GRPC_CALL_OK);
202*cc02d7e2SAndroid Build Coastguard Worker   // No interceptors to run here
203*cc02d7e2SAndroid Build Coastguard Worker }
204*cc02d7e2SAndroid Build Coastguard Worker 
FinalizeResult(void ** tag,bool * status)205*cc02d7e2SAndroid Build Coastguard Worker bool ServerContextBase::CompletionOp::FinalizeResult(void** tag, bool* status) {
206*cc02d7e2SAndroid Build Coastguard Worker   // Decide whether to do the unref or call the cancel callback within the lock
207*cc02d7e2SAndroid Build Coastguard Worker   bool do_unref = false;
208*cc02d7e2SAndroid Build Coastguard Worker   bool has_tag = false;
209*cc02d7e2SAndroid Build Coastguard Worker   bool call_cancel = false;
210*cc02d7e2SAndroid Build Coastguard Worker 
211*cc02d7e2SAndroid Build Coastguard Worker   {
212*cc02d7e2SAndroid Build Coastguard Worker     grpc_core::MutexLock lock(&mu_);
213*cc02d7e2SAndroid Build Coastguard Worker     if (done_intercepting_) {
214*cc02d7e2SAndroid Build Coastguard Worker       // We are done intercepting.
215*cc02d7e2SAndroid Build Coastguard Worker       has_tag = has_tag_;
216*cc02d7e2SAndroid Build Coastguard Worker       if (has_tag) {
217*cc02d7e2SAndroid Build Coastguard Worker         *tag = tag_;
218*cc02d7e2SAndroid Build Coastguard Worker       }
219*cc02d7e2SAndroid Build Coastguard Worker       // Release the lock before unreffing as Unref may delete this object
220*cc02d7e2SAndroid Build Coastguard Worker       do_unref = true;
221*cc02d7e2SAndroid Build Coastguard Worker     } else {
222*cc02d7e2SAndroid Build Coastguard Worker       finalized_ = true;
223*cc02d7e2SAndroid Build Coastguard Worker 
224*cc02d7e2SAndroid Build Coastguard Worker       // If for some reason the incoming status is false, mark that as a
225*cc02d7e2SAndroid Build Coastguard Worker       // cancellation.
226*cc02d7e2SAndroid Build Coastguard Worker       // TODO(vjpai): does this ever happen?
227*cc02d7e2SAndroid Build Coastguard Worker       if (!*status) {
228*cc02d7e2SAndroid Build Coastguard Worker         cancelled_ = 1;
229*cc02d7e2SAndroid Build Coastguard Worker       }
230*cc02d7e2SAndroid Build Coastguard Worker 
231*cc02d7e2SAndroid Build Coastguard Worker       call_cancel = (cancelled_ != 0);
232*cc02d7e2SAndroid Build Coastguard Worker       // Release the lock since we may call a callback and interceptors.
233*cc02d7e2SAndroid Build Coastguard Worker     }
234*cc02d7e2SAndroid Build Coastguard Worker   }
235*cc02d7e2SAndroid Build Coastguard Worker 
236*cc02d7e2SAndroid Build Coastguard Worker   if (do_unref) {
237*cc02d7e2SAndroid Build Coastguard Worker     Unref();
238*cc02d7e2SAndroid Build Coastguard Worker     // Unref can delete this, so do not access anything from this afterward.
239*cc02d7e2SAndroid Build Coastguard Worker     return has_tag;
240*cc02d7e2SAndroid Build Coastguard Worker   }
241*cc02d7e2SAndroid Build Coastguard Worker   if (call_cancel && callback_controller_ != nullptr) {
242*cc02d7e2SAndroid Build Coastguard Worker     callback_controller_->MaybeCallOnCancel();
243*cc02d7e2SAndroid Build Coastguard Worker   }
244*cc02d7e2SAndroid Build Coastguard Worker   // Add interception point and run through interceptors
245*cc02d7e2SAndroid Build Coastguard Worker   interceptor_methods_.AddInterceptionHookPoint(
246*cc02d7e2SAndroid Build Coastguard Worker       experimental::InterceptionHookPoints::POST_RECV_CLOSE);
247*cc02d7e2SAndroid Build Coastguard Worker   if (interceptor_methods_.RunInterceptors()) {
248*cc02d7e2SAndroid Build Coastguard Worker     // No interceptors were run
249*cc02d7e2SAndroid Build Coastguard Worker     bool has_tag = has_tag_;
250*cc02d7e2SAndroid Build Coastguard Worker     if (has_tag) {
251*cc02d7e2SAndroid Build Coastguard Worker       *tag = tag_;
252*cc02d7e2SAndroid Build Coastguard Worker     }
253*cc02d7e2SAndroid Build Coastguard Worker     Unref();
254*cc02d7e2SAndroid Build Coastguard Worker     // Unref can delete this, so do not access anything from this afterward.
255*cc02d7e2SAndroid Build Coastguard Worker     return has_tag;
256*cc02d7e2SAndroid Build Coastguard Worker   }
257*cc02d7e2SAndroid Build Coastguard Worker   // There are interceptors to be run. Return false for now.
258*cc02d7e2SAndroid Build Coastguard Worker   return false;
259*cc02d7e2SAndroid Build Coastguard Worker }
260*cc02d7e2SAndroid Build Coastguard Worker 
261*cc02d7e2SAndroid Build Coastguard Worker // ServerContextBase body
262*cc02d7e2SAndroid Build Coastguard Worker 
ServerContextBase()263*cc02d7e2SAndroid Build Coastguard Worker ServerContextBase::ServerContextBase()
264*cc02d7e2SAndroid Build Coastguard Worker     : deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)) {}
265*cc02d7e2SAndroid Build Coastguard Worker 
ServerContextBase(gpr_timespec deadline,grpc_metadata_array * arr)266*cc02d7e2SAndroid Build Coastguard Worker ServerContextBase::ServerContextBase(gpr_timespec deadline,
267*cc02d7e2SAndroid Build Coastguard Worker                                      grpc_metadata_array* arr)
268*cc02d7e2SAndroid Build Coastguard Worker     : deadline_(deadline) {
269*cc02d7e2SAndroid Build Coastguard Worker   std::swap(*client_metadata_.arr(), *arr);
270*cc02d7e2SAndroid Build Coastguard Worker }
271*cc02d7e2SAndroid Build Coastguard Worker 
BindDeadlineAndMetadata(gpr_timespec deadline,grpc_metadata_array * arr)272*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::BindDeadlineAndMetadata(gpr_timespec deadline,
273*cc02d7e2SAndroid Build Coastguard Worker                                                 grpc_metadata_array* arr) {
274*cc02d7e2SAndroid Build Coastguard Worker   deadline_ = deadline;
275*cc02d7e2SAndroid Build Coastguard Worker   std::swap(*client_metadata_.arr(), *arr);
276*cc02d7e2SAndroid Build Coastguard Worker }
277*cc02d7e2SAndroid Build Coastguard Worker 
~ServerContextBase()278*cc02d7e2SAndroid Build Coastguard Worker ServerContextBase::~ServerContextBase() {
279*cc02d7e2SAndroid Build Coastguard Worker   if (completion_op_) {
280*cc02d7e2SAndroid Build Coastguard Worker     completion_op_->Unref();
281*cc02d7e2SAndroid Build Coastguard Worker     // Unref can delete completion_op_, so do not access it afterward.
282*cc02d7e2SAndroid Build Coastguard Worker   }
283*cc02d7e2SAndroid Build Coastguard Worker   if (rpc_info_) {
284*cc02d7e2SAndroid Build Coastguard Worker     rpc_info_->Unref();
285*cc02d7e2SAndroid Build Coastguard Worker   }
286*cc02d7e2SAndroid Build Coastguard Worker   if (default_reactor_used_.load(std::memory_order_relaxed)) {
287*cc02d7e2SAndroid Build Coastguard Worker     reinterpret_cast<Reactor*>(&default_reactor_)->~Reactor();
288*cc02d7e2SAndroid Build Coastguard Worker   }
289*cc02d7e2SAndroid Build Coastguard Worker   if (call_metric_recorder_ != nullptr) {
290*cc02d7e2SAndroid Build Coastguard Worker     call_metric_recorder_->~CallMetricRecorder();
291*cc02d7e2SAndroid Build Coastguard Worker   }
292*cc02d7e2SAndroid Build Coastguard Worker }
293*cc02d7e2SAndroid Build Coastguard Worker 
~CallWrapper()294*cc02d7e2SAndroid Build Coastguard Worker ServerContextBase::CallWrapper::~CallWrapper() {
295*cc02d7e2SAndroid Build Coastguard Worker   if (call) {
296*cc02d7e2SAndroid Build Coastguard Worker     // If the ServerContext is part of the call's arena, this could free the
297*cc02d7e2SAndroid Build Coastguard Worker     // object itself.
298*cc02d7e2SAndroid Build Coastguard Worker     grpc_call_unref(call);
299*cc02d7e2SAndroid Build Coastguard Worker   }
300*cc02d7e2SAndroid Build Coastguard Worker }
301*cc02d7e2SAndroid Build Coastguard Worker 
BeginCompletionOp(internal::Call * call,std::function<void (bool)> callback,grpc::internal::ServerCallbackCall * callback_controller)302*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::BeginCompletionOp(
303*cc02d7e2SAndroid Build Coastguard Worker     internal::Call* call, std::function<void(bool)> callback,
304*cc02d7e2SAndroid Build Coastguard Worker     grpc::internal::ServerCallbackCall* callback_controller) {
305*cc02d7e2SAndroid Build Coastguard Worker   GPR_ASSERT(!completion_op_);
306*cc02d7e2SAndroid Build Coastguard Worker   if (rpc_info_) {
307*cc02d7e2SAndroid Build Coastguard Worker     rpc_info_->Ref();
308*cc02d7e2SAndroid Build Coastguard Worker   }
309*cc02d7e2SAndroid Build Coastguard Worker   grpc_call_ref(call->call());
310*cc02d7e2SAndroid Build Coastguard Worker   completion_op_ =
311*cc02d7e2SAndroid Build Coastguard Worker       new (grpc_call_arena_alloc(call->call(), sizeof(CompletionOp)))
312*cc02d7e2SAndroid Build Coastguard Worker           CompletionOp(call, callback_controller);
313*cc02d7e2SAndroid Build Coastguard Worker   if (callback_controller != nullptr) {
314*cc02d7e2SAndroid Build Coastguard Worker     completion_tag_.Set(call->call(), std::move(callback), completion_op_,
315*cc02d7e2SAndroid Build Coastguard Worker                         true);
316*cc02d7e2SAndroid Build Coastguard Worker     completion_op_->set_core_cq_tag(&completion_tag_);
317*cc02d7e2SAndroid Build Coastguard Worker     completion_op_->set_tag(completion_op_);
318*cc02d7e2SAndroid Build Coastguard Worker   } else if (has_notify_when_done_tag_) {
319*cc02d7e2SAndroid Build Coastguard Worker     completion_op_->set_tag(async_notify_when_done_tag_);
320*cc02d7e2SAndroid Build Coastguard Worker   }
321*cc02d7e2SAndroid Build Coastguard Worker   call->PerformOps(completion_op_);
322*cc02d7e2SAndroid Build Coastguard Worker }
323*cc02d7e2SAndroid Build Coastguard Worker 
GetCompletionOpTag()324*cc02d7e2SAndroid Build Coastguard Worker internal::CompletionQueueTag* ServerContextBase::GetCompletionOpTag() {
325*cc02d7e2SAndroid Build Coastguard Worker   return static_cast<internal::CompletionQueueTag*>(completion_op_);
326*cc02d7e2SAndroid Build Coastguard Worker }
327*cc02d7e2SAndroid Build Coastguard Worker 
AddInitialMetadata(const std::string & key,const std::string & value)328*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::AddInitialMetadata(const std::string& key,
329*cc02d7e2SAndroid Build Coastguard Worker                                            const std::string& value) {
330*cc02d7e2SAndroid Build Coastguard Worker   initial_metadata_.insert(std::make_pair(key, value));
331*cc02d7e2SAndroid Build Coastguard Worker }
332*cc02d7e2SAndroid Build Coastguard Worker 
AddTrailingMetadata(const std::string & key,const std::string & value)333*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::AddTrailingMetadata(const std::string& key,
334*cc02d7e2SAndroid Build Coastguard Worker                                             const std::string& value) {
335*cc02d7e2SAndroid Build Coastguard Worker   trailing_metadata_.insert(std::make_pair(key, value));
336*cc02d7e2SAndroid Build Coastguard Worker }
337*cc02d7e2SAndroid Build Coastguard Worker 
TryCancel() const338*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::TryCancel() const {
339*cc02d7e2SAndroid Build Coastguard Worker   internal::CancelInterceptorBatchMethods cancel_methods;
340*cc02d7e2SAndroid Build Coastguard Worker   if (rpc_info_) {
341*cc02d7e2SAndroid Build Coastguard Worker     for (size_t i = 0; i < rpc_info_->interceptors_.size(); i++) {
342*cc02d7e2SAndroid Build Coastguard Worker       rpc_info_->RunInterceptor(&cancel_methods, i);
343*cc02d7e2SAndroid Build Coastguard Worker     }
344*cc02d7e2SAndroid Build Coastguard Worker   }
345*cc02d7e2SAndroid Build Coastguard Worker   grpc_call_error err =
346*cc02d7e2SAndroid Build Coastguard Worker       grpc_call_cancel_with_status(call_.call, GRPC_STATUS_CANCELLED,
347*cc02d7e2SAndroid Build Coastguard Worker                                    "Cancelled on the server side", nullptr);
348*cc02d7e2SAndroid Build Coastguard Worker   if (err != GRPC_CALL_OK) {
349*cc02d7e2SAndroid Build Coastguard Worker     gpr_log(GPR_ERROR, "TryCancel failed with: %d", err);
350*cc02d7e2SAndroid Build Coastguard Worker   }
351*cc02d7e2SAndroid Build Coastguard Worker }
352*cc02d7e2SAndroid Build Coastguard Worker 
IsCancelled() const353*cc02d7e2SAndroid Build Coastguard Worker bool ServerContextBase::IsCancelled() const {
354*cc02d7e2SAndroid Build Coastguard Worker   if (completion_tag_) {
355*cc02d7e2SAndroid Build Coastguard Worker     // When using callback API, this result is always valid.
356*cc02d7e2SAndroid Build Coastguard Worker     return marked_cancelled_.load(std::memory_order_acquire) ||
357*cc02d7e2SAndroid Build Coastguard Worker            completion_op_->CheckCancelledAsync();
358*cc02d7e2SAndroid Build Coastguard Worker   } else if (has_notify_when_done_tag_) {
359*cc02d7e2SAndroid Build Coastguard Worker     // When using async API, the result is only valid
360*cc02d7e2SAndroid Build Coastguard Worker     // if the tag has already been delivered at the completion queue
361*cc02d7e2SAndroid Build Coastguard Worker     return completion_op_ && completion_op_->CheckCancelledAsync();
362*cc02d7e2SAndroid Build Coastguard Worker   } else {
363*cc02d7e2SAndroid Build Coastguard Worker     // when using sync API, the result is always valid
364*cc02d7e2SAndroid Build Coastguard Worker     return marked_cancelled_.load(std::memory_order_acquire) ||
365*cc02d7e2SAndroid Build Coastguard Worker            (completion_op_ && completion_op_->CheckCancelled(cq_));
366*cc02d7e2SAndroid Build Coastguard Worker   }
367*cc02d7e2SAndroid Build Coastguard Worker }
368*cc02d7e2SAndroid Build Coastguard Worker 
set_compression_algorithm(grpc_compression_algorithm algorithm)369*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::set_compression_algorithm(
370*cc02d7e2SAndroid Build Coastguard Worker     grpc_compression_algorithm algorithm) {
371*cc02d7e2SAndroid Build Coastguard Worker   compression_algorithm_ = algorithm;
372*cc02d7e2SAndroid Build Coastguard Worker   const char* algorithm_name = nullptr;
373*cc02d7e2SAndroid Build Coastguard Worker   if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) {
374*cc02d7e2SAndroid Build Coastguard Worker     grpc_core::Crash(absl::StrFormat(
375*cc02d7e2SAndroid Build Coastguard Worker         "Name for compression algorithm '%d' unknown.", algorithm));
376*cc02d7e2SAndroid Build Coastguard Worker   }
377*cc02d7e2SAndroid Build Coastguard Worker   GPR_ASSERT(algorithm_name != nullptr);
378*cc02d7e2SAndroid Build Coastguard Worker   AddInitialMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name);
379*cc02d7e2SAndroid Build Coastguard Worker }
380*cc02d7e2SAndroid Build Coastguard Worker 
peer() const381*cc02d7e2SAndroid Build Coastguard Worker std::string ServerContextBase::peer() const {
382*cc02d7e2SAndroid Build Coastguard Worker   std::string peer;
383*cc02d7e2SAndroid Build Coastguard Worker   if (call_.call) {
384*cc02d7e2SAndroid Build Coastguard Worker     char* c_peer = grpc_call_get_peer(call_.call);
385*cc02d7e2SAndroid Build Coastguard Worker     peer = c_peer;
386*cc02d7e2SAndroid Build Coastguard Worker     gpr_free(c_peer);
387*cc02d7e2SAndroid Build Coastguard Worker   }
388*cc02d7e2SAndroid Build Coastguard Worker   return peer;
389*cc02d7e2SAndroid Build Coastguard Worker }
390*cc02d7e2SAndroid Build Coastguard Worker 
census_context() const391*cc02d7e2SAndroid Build Coastguard Worker const struct census_context* ServerContextBase::census_context() const {
392*cc02d7e2SAndroid Build Coastguard Worker   return call_.call == nullptr ? nullptr
393*cc02d7e2SAndroid Build Coastguard Worker                                : grpc_census_call_get_context(call_.call);
394*cc02d7e2SAndroid Build Coastguard Worker }
395*cc02d7e2SAndroid Build Coastguard Worker 
SetLoadReportingCosts(const std::vector<std::string> & cost_data)396*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::SetLoadReportingCosts(
397*cc02d7e2SAndroid Build Coastguard Worker     const std::vector<std::string>& cost_data) {
398*cc02d7e2SAndroid Build Coastguard Worker   if (call_.call == nullptr) return;
399*cc02d7e2SAndroid Build Coastguard Worker   for (const auto& cost_datum : cost_data) {
400*cc02d7e2SAndroid Build Coastguard Worker     AddTrailingMetadata(GRPC_LB_COST_MD_KEY, cost_datum);
401*cc02d7e2SAndroid Build Coastguard Worker   }
402*cc02d7e2SAndroid Build Coastguard Worker }
403*cc02d7e2SAndroid Build Coastguard Worker 
CreateCallMetricRecorder(experimental::ServerMetricRecorder * server_metric_recorder)404*cc02d7e2SAndroid Build Coastguard Worker void ServerContextBase::CreateCallMetricRecorder(
405*cc02d7e2SAndroid Build Coastguard Worker     experimental::ServerMetricRecorder* server_metric_recorder) {
406*cc02d7e2SAndroid Build Coastguard Worker   if (call_.call == nullptr) return;
407*cc02d7e2SAndroid Build Coastguard Worker   GPR_ASSERT(call_metric_recorder_ == nullptr);
408*cc02d7e2SAndroid Build Coastguard Worker   grpc_core::Arena* arena = grpc_call_get_arena(call_.call);
409*cc02d7e2SAndroid Build Coastguard Worker   auto* backend_metric_state =
410*cc02d7e2SAndroid Build Coastguard Worker       arena->New<BackendMetricState>(server_metric_recorder);
411*cc02d7e2SAndroid Build Coastguard Worker   call_metric_recorder_ = backend_metric_state;
412*cc02d7e2SAndroid Build Coastguard Worker   grpc_call_context_set(call_.call, GRPC_CONTEXT_BACKEND_METRIC_PROVIDER,
413*cc02d7e2SAndroid Build Coastguard Worker                         backend_metric_state, nullptr);
414*cc02d7e2SAndroid Build Coastguard Worker }
415*cc02d7e2SAndroid Build Coastguard Worker 
ExperimentalGetAuthority() const416*cc02d7e2SAndroid Build Coastguard Worker grpc::string_ref ServerContextBase::ExperimentalGetAuthority() const {
417*cc02d7e2SAndroid Build Coastguard Worker   absl::string_view authority = grpc_call_server_authority(call_.call);
418*cc02d7e2SAndroid Build Coastguard Worker   return grpc::string_ref(authority.data(), authority.size());
419*cc02d7e2SAndroid Build Coastguard Worker }
420*cc02d7e2SAndroid Build Coastguard Worker 
421*cc02d7e2SAndroid Build Coastguard Worker }  // namespace grpc
422