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 <stdlib.h>
20*cc02d7e2SAndroid Build Coastguard Worker
21*cc02d7e2SAndroid Build Coastguard Worker #include <map>
22*cc02d7e2SAndroid Build Coastguard Worker #include <memory>
23*cc02d7e2SAndroid Build Coastguard Worker #include <string>
24*cc02d7e2SAndroid Build Coastguard Worker #include <utility>
25*cc02d7e2SAndroid Build Coastguard Worker #include <vector>
26*cc02d7e2SAndroid Build Coastguard Worker
27*cc02d7e2SAndroid Build Coastguard Worker #include "absl/strings/str_format.h"
28*cc02d7e2SAndroid Build Coastguard Worker
29*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/compression.h>
30*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/grpc.h>
31*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/impl/compression_types.h>
32*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/status.h>
33*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/alloc.h>
34*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/log.h>
35*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/time.h>
36*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/channel.h>
37*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/client_context.h>
38*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/interceptor_common.h>
39*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/sync.h>
40*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/security/credentials.h>
41*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/server_context.h>
42*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/client_interceptor.h>
43*cc02d7e2SAndroid Build Coastguard Worker
44*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/crash.h"
45*cc02d7e2SAndroid Build Coastguard Worker
46*cc02d7e2SAndroid Build Coastguard Worker namespace grpc {
47*cc02d7e2SAndroid Build Coastguard Worker
48*cc02d7e2SAndroid Build Coastguard Worker class Channel;
49*cc02d7e2SAndroid Build Coastguard Worker
50*cc02d7e2SAndroid Build Coastguard Worker class DefaultGlobalClientCallbacks final
51*cc02d7e2SAndroid Build Coastguard Worker : public ClientContext::GlobalCallbacks {
52*cc02d7e2SAndroid Build Coastguard Worker public:
~DefaultGlobalClientCallbacks()53*cc02d7e2SAndroid Build Coastguard Worker ~DefaultGlobalClientCallbacks() override {}
DefaultConstructor(ClientContext *)54*cc02d7e2SAndroid Build Coastguard Worker void DefaultConstructor(ClientContext* /*context*/) override {}
Destructor(ClientContext *)55*cc02d7e2SAndroid Build Coastguard Worker void Destructor(ClientContext* /*context*/) override {}
56*cc02d7e2SAndroid Build Coastguard Worker };
57*cc02d7e2SAndroid Build Coastguard Worker
58*cc02d7e2SAndroid Build Coastguard Worker static DefaultGlobalClientCallbacks* g_default_client_callbacks =
59*cc02d7e2SAndroid Build Coastguard Worker new DefaultGlobalClientCallbacks();
60*cc02d7e2SAndroid Build Coastguard Worker static ClientContext::GlobalCallbacks* g_client_callbacks =
61*cc02d7e2SAndroid Build Coastguard Worker g_default_client_callbacks;
62*cc02d7e2SAndroid Build Coastguard Worker
ClientContext()63*cc02d7e2SAndroid Build Coastguard Worker ClientContext::ClientContext()
64*cc02d7e2SAndroid Build Coastguard Worker : initial_metadata_received_(false),
65*cc02d7e2SAndroid Build Coastguard Worker wait_for_ready_(false),
66*cc02d7e2SAndroid Build Coastguard Worker wait_for_ready_explicitly_set_(false),
67*cc02d7e2SAndroid Build Coastguard Worker call_(nullptr),
68*cc02d7e2SAndroid Build Coastguard Worker call_canceled_(false),
69*cc02d7e2SAndroid Build Coastguard Worker deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
70*cc02d7e2SAndroid Build Coastguard Worker census_context_(nullptr),
71*cc02d7e2SAndroid Build Coastguard Worker propagate_from_call_(nullptr),
72*cc02d7e2SAndroid Build Coastguard Worker compression_algorithm_(GRPC_COMPRESS_NONE),
73*cc02d7e2SAndroid Build Coastguard Worker initial_metadata_corked_(false) {
74*cc02d7e2SAndroid Build Coastguard Worker g_client_callbacks->DefaultConstructor(this);
75*cc02d7e2SAndroid Build Coastguard Worker }
76*cc02d7e2SAndroid Build Coastguard Worker
~ClientContext()77*cc02d7e2SAndroid Build Coastguard Worker ClientContext::~ClientContext() {
78*cc02d7e2SAndroid Build Coastguard Worker if (call_) {
79*cc02d7e2SAndroid Build Coastguard Worker grpc_call_unref(call_);
80*cc02d7e2SAndroid Build Coastguard Worker call_ = nullptr;
81*cc02d7e2SAndroid Build Coastguard Worker }
82*cc02d7e2SAndroid Build Coastguard Worker g_client_callbacks->Destructor(this);
83*cc02d7e2SAndroid Build Coastguard Worker }
84*cc02d7e2SAndroid Build Coastguard Worker
set_credentials(const std::shared_ptr<CallCredentials> & creds)85*cc02d7e2SAndroid Build Coastguard Worker void ClientContext::set_credentials(
86*cc02d7e2SAndroid Build Coastguard Worker const std::shared_ptr<CallCredentials>& creds) {
87*cc02d7e2SAndroid Build Coastguard Worker creds_ = creds;
88*cc02d7e2SAndroid Build Coastguard Worker // If call_ is set, we have already created the call, and set the call
89*cc02d7e2SAndroid Build Coastguard Worker // credentials. This should only be done before we have started the batch
90*cc02d7e2SAndroid Build Coastguard Worker // for sending initial metadata.
91*cc02d7e2SAndroid Build Coastguard Worker if (creds_ != nullptr && call_ != nullptr) {
92*cc02d7e2SAndroid Build Coastguard Worker if (!creds_->ApplyToCall(call_)) {
93*cc02d7e2SAndroid Build Coastguard Worker SendCancelToInterceptors();
94*cc02d7e2SAndroid Build Coastguard Worker grpc_call_cancel_with_status(call_, GRPC_STATUS_CANCELLED,
95*cc02d7e2SAndroid Build Coastguard Worker "Failed to set credentials to rpc.",
96*cc02d7e2SAndroid Build Coastguard Worker nullptr);
97*cc02d7e2SAndroid Build Coastguard Worker }
98*cc02d7e2SAndroid Build Coastguard Worker }
99*cc02d7e2SAndroid Build Coastguard Worker }
100*cc02d7e2SAndroid Build Coastguard Worker
FromInternalServerContext(const grpc::ServerContextBase & context,PropagationOptions options)101*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<ClientContext> ClientContext::FromInternalServerContext(
102*cc02d7e2SAndroid Build Coastguard Worker const grpc::ServerContextBase& context, PropagationOptions options) {
103*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<ClientContext> ctx(new ClientContext);
104*cc02d7e2SAndroid Build Coastguard Worker ctx->propagate_from_call_ = context.call_.call;
105*cc02d7e2SAndroid Build Coastguard Worker ctx->propagation_options_ = options;
106*cc02d7e2SAndroid Build Coastguard Worker return ctx;
107*cc02d7e2SAndroid Build Coastguard Worker }
108*cc02d7e2SAndroid Build Coastguard Worker
FromServerContext(const grpc::ServerContextBase & server_context,PropagationOptions options)109*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<ClientContext> ClientContext::FromServerContext(
110*cc02d7e2SAndroid Build Coastguard Worker const grpc::ServerContextBase& server_context, PropagationOptions options) {
111*cc02d7e2SAndroid Build Coastguard Worker return FromInternalServerContext(server_context, options);
112*cc02d7e2SAndroid Build Coastguard Worker }
113*cc02d7e2SAndroid Build Coastguard Worker
FromCallbackServerContext(const grpc::CallbackServerContext & server_context,PropagationOptions options)114*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<ClientContext> ClientContext::FromCallbackServerContext(
115*cc02d7e2SAndroid Build Coastguard Worker const grpc::CallbackServerContext& server_context,
116*cc02d7e2SAndroid Build Coastguard Worker PropagationOptions options) {
117*cc02d7e2SAndroid Build Coastguard Worker return FromInternalServerContext(server_context, options);
118*cc02d7e2SAndroid Build Coastguard Worker }
119*cc02d7e2SAndroid Build Coastguard Worker
AddMetadata(const std::string & meta_key,const std::string & meta_value)120*cc02d7e2SAndroid Build Coastguard Worker void ClientContext::AddMetadata(const std::string& meta_key,
121*cc02d7e2SAndroid Build Coastguard Worker const std::string& meta_value) {
122*cc02d7e2SAndroid Build Coastguard Worker send_initial_metadata_.insert(std::make_pair(meta_key, meta_value));
123*cc02d7e2SAndroid Build Coastguard Worker }
124*cc02d7e2SAndroid Build Coastguard Worker
set_call(grpc_call * call,const std::shared_ptr<Channel> & channel)125*cc02d7e2SAndroid Build Coastguard Worker void ClientContext::set_call(grpc_call* call,
126*cc02d7e2SAndroid Build Coastguard Worker const std::shared_ptr<Channel>& channel) {
127*cc02d7e2SAndroid Build Coastguard Worker internal::MutexLock lock(&mu_);
128*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(call_ == nullptr);
129*cc02d7e2SAndroid Build Coastguard Worker call_ = call;
130*cc02d7e2SAndroid Build Coastguard Worker channel_ = channel;
131*cc02d7e2SAndroid Build Coastguard Worker if (creds_ && !creds_->ApplyToCall(call_)) {
132*cc02d7e2SAndroid Build Coastguard Worker // TODO(yashykt): should interceptors also see this status?
133*cc02d7e2SAndroid Build Coastguard Worker SendCancelToInterceptors();
134*cc02d7e2SAndroid Build Coastguard Worker grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED,
135*cc02d7e2SAndroid Build Coastguard Worker "Failed to set credentials to rpc.", nullptr);
136*cc02d7e2SAndroid Build Coastguard Worker }
137*cc02d7e2SAndroid Build Coastguard Worker if (call_canceled_) {
138*cc02d7e2SAndroid Build Coastguard Worker SendCancelToInterceptors();
139*cc02d7e2SAndroid Build Coastguard Worker grpc_call_cancel(call_, nullptr);
140*cc02d7e2SAndroid Build Coastguard Worker }
141*cc02d7e2SAndroid Build Coastguard Worker }
142*cc02d7e2SAndroid Build Coastguard Worker
set_compression_algorithm(grpc_compression_algorithm algorithm)143*cc02d7e2SAndroid Build Coastguard Worker void ClientContext::set_compression_algorithm(
144*cc02d7e2SAndroid Build Coastguard Worker grpc_compression_algorithm algorithm) {
145*cc02d7e2SAndroid Build Coastguard Worker compression_algorithm_ = algorithm;
146*cc02d7e2SAndroid Build Coastguard Worker const char* algorithm_name = nullptr;
147*cc02d7e2SAndroid Build Coastguard Worker if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) {
148*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Crash(absl::StrFormat(
149*cc02d7e2SAndroid Build Coastguard Worker "Name for compression algorithm '%d' unknown.", algorithm));
150*cc02d7e2SAndroid Build Coastguard Worker }
151*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(algorithm_name != nullptr);
152*cc02d7e2SAndroid Build Coastguard Worker AddMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name);
153*cc02d7e2SAndroid Build Coastguard Worker }
154*cc02d7e2SAndroid Build Coastguard Worker
TryCancel()155*cc02d7e2SAndroid Build Coastguard Worker void ClientContext::TryCancel() {
156*cc02d7e2SAndroid Build Coastguard Worker internal::MutexLock lock(&mu_);
157*cc02d7e2SAndroid Build Coastguard Worker if (call_) {
158*cc02d7e2SAndroid Build Coastguard Worker SendCancelToInterceptors();
159*cc02d7e2SAndroid Build Coastguard Worker grpc_call_cancel(call_, nullptr);
160*cc02d7e2SAndroid Build Coastguard Worker } else {
161*cc02d7e2SAndroid Build Coastguard Worker call_canceled_ = true;
162*cc02d7e2SAndroid Build Coastguard Worker }
163*cc02d7e2SAndroid Build Coastguard Worker }
164*cc02d7e2SAndroid Build Coastguard Worker
SendCancelToInterceptors()165*cc02d7e2SAndroid Build Coastguard Worker void ClientContext::SendCancelToInterceptors() {
166*cc02d7e2SAndroid Build Coastguard Worker internal::CancelInterceptorBatchMethods cancel_methods;
167*cc02d7e2SAndroid Build Coastguard Worker for (size_t i = 0; i < rpc_info_.interceptors_.size(); i++) {
168*cc02d7e2SAndroid Build Coastguard Worker rpc_info_.RunInterceptor(&cancel_methods, i);
169*cc02d7e2SAndroid Build Coastguard Worker }
170*cc02d7e2SAndroid Build Coastguard Worker }
171*cc02d7e2SAndroid Build Coastguard Worker
peer() const172*cc02d7e2SAndroid Build Coastguard Worker std::string ClientContext::peer() const {
173*cc02d7e2SAndroid Build Coastguard Worker std::string peer;
174*cc02d7e2SAndroid Build Coastguard Worker if (call_) {
175*cc02d7e2SAndroid Build Coastguard Worker char* c_peer = grpc_call_get_peer(call_);
176*cc02d7e2SAndroid Build Coastguard Worker peer = c_peer;
177*cc02d7e2SAndroid Build Coastguard Worker gpr_free(c_peer);
178*cc02d7e2SAndroid Build Coastguard Worker }
179*cc02d7e2SAndroid Build Coastguard Worker return peer;
180*cc02d7e2SAndroid Build Coastguard Worker }
181*cc02d7e2SAndroid Build Coastguard Worker
SetGlobalCallbacks(GlobalCallbacks * client_callbacks)182*cc02d7e2SAndroid Build Coastguard Worker void ClientContext::SetGlobalCallbacks(GlobalCallbacks* client_callbacks) {
183*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(g_client_callbacks == g_default_client_callbacks);
184*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(client_callbacks != nullptr);
185*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(client_callbacks != g_default_client_callbacks);
186*cc02d7e2SAndroid Build Coastguard Worker g_client_callbacks = client_callbacks;
187*cc02d7e2SAndroid Build Coastguard Worker }
188*cc02d7e2SAndroid Build Coastguard Worker
189*cc02d7e2SAndroid Build Coastguard Worker } // namespace grpc
190