| // |
| // |
| // Copyright 2015 gRPC authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // |
| |
| #include <stdlib.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/strings/str_format.h" |
| |
| #include <grpc/compression.h> |
| #include <grpc/grpc.h> |
| #include <grpc/impl/compression_types.h> |
| #include <grpc/status.h> |
| #include <grpc/support/alloc.h> |
| #include <grpc/support/log.h> |
| #include <grpc/support/time.h> |
| #include <grpcpp/channel.h> |
| #include <grpcpp/client_context.h> |
| #include <grpcpp/impl/interceptor_common.h> |
| #include <grpcpp/impl/sync.h> |
| #include <grpcpp/security/credentials.h> |
| #include <grpcpp/server_context.h> |
| #include <grpcpp/support/client_interceptor.h> |
| |
| #include "src/core/lib/gprpp/crash.h" |
| |
| namespace grpc { |
| |
| class Channel; |
| |
| class DefaultGlobalClientCallbacks final |
| : public ClientContext::GlobalCallbacks { |
| public: |
| ~DefaultGlobalClientCallbacks() override {} |
| void DefaultConstructor(ClientContext* /*context*/) override {} |
| void Destructor(ClientContext* /*context*/) override {} |
| }; |
| |
| static DefaultGlobalClientCallbacks* g_default_client_callbacks = |
| new DefaultGlobalClientCallbacks(); |
| static ClientContext::GlobalCallbacks* g_client_callbacks = |
| g_default_client_callbacks; |
| |
| ClientContext::ClientContext() |
| : initial_metadata_received_(false), |
| wait_for_ready_(false), |
| wait_for_ready_explicitly_set_(false), |
| call_(nullptr), |
| call_canceled_(false), |
| deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)), |
| census_context_(nullptr), |
| propagate_from_call_(nullptr), |
| compression_algorithm_(GRPC_COMPRESS_NONE), |
| initial_metadata_corked_(false) { |
| g_client_callbacks->DefaultConstructor(this); |
| } |
| |
| ClientContext::~ClientContext() { |
| if (call_) { |
| grpc_call_unref(call_); |
| call_ = nullptr; |
| } |
| g_client_callbacks->Destructor(this); |
| } |
| |
| void ClientContext::set_credentials( |
| const std::shared_ptr<CallCredentials>& creds) { |
| creds_ = creds; |
| // If call_ is set, we have already created the call, and set the call |
| // credentials. This should only be done before we have started the batch |
| // for sending initial metadata. |
| if (creds_ != nullptr && call_ != nullptr) { |
| if (!creds_->ApplyToCall(call_)) { |
| SendCancelToInterceptors(); |
| grpc_call_cancel_with_status(call_, GRPC_STATUS_CANCELLED, |
| "Failed to set credentials to rpc.", |
| nullptr); |
| } |
| } |
| } |
| |
| std::unique_ptr<ClientContext> ClientContext::FromInternalServerContext( |
| const grpc::ServerContextBase& context, PropagationOptions options) { |
| std::unique_ptr<ClientContext> ctx(new ClientContext); |
| ctx->propagate_from_call_ = context.call_.call; |
| ctx->propagation_options_ = options; |
| return ctx; |
| } |
| |
| std::unique_ptr<ClientContext> ClientContext::FromServerContext( |
| const grpc::ServerContextBase& server_context, PropagationOptions options) { |
| return FromInternalServerContext(server_context, options); |
| } |
| |
| std::unique_ptr<ClientContext> ClientContext::FromCallbackServerContext( |
| const grpc::CallbackServerContext& server_context, |
| PropagationOptions options) { |
| return FromInternalServerContext(server_context, options); |
| } |
| |
| void ClientContext::AddMetadata(const std::string& meta_key, |
| const std::string& meta_value) { |
| send_initial_metadata_.insert(std::make_pair(meta_key, meta_value)); |
| } |
| |
| void ClientContext::set_call(grpc_call* call, |
| const std::shared_ptr<Channel>& channel) { |
| internal::MutexLock lock(&mu_); |
| GPR_ASSERT(call_ == nullptr); |
| call_ = call; |
| channel_ = channel; |
| if (creds_ && !creds_->ApplyToCall(call_)) { |
| // TODO(yashykt): should interceptors also see this status? |
| SendCancelToInterceptors(); |
| grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, |
| "Failed to set credentials to rpc.", nullptr); |
| } |
| if (call_canceled_) { |
| SendCancelToInterceptors(); |
| grpc_call_cancel(call_, nullptr); |
| } |
| } |
| |
| void ClientContext::set_compression_algorithm( |
| grpc_compression_algorithm algorithm) { |
| compression_algorithm_ = algorithm; |
| const char* algorithm_name = nullptr; |
| if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) { |
| grpc_core::Crash(absl::StrFormat( |
| "Name for compression algorithm '%d' unknown.", algorithm)); |
| } |
| GPR_ASSERT(algorithm_name != nullptr); |
| AddMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name); |
| } |
| |
| void ClientContext::TryCancel() { |
| internal::MutexLock lock(&mu_); |
| if (call_) { |
| SendCancelToInterceptors(); |
| grpc_call_cancel(call_, nullptr); |
| } else { |
| call_canceled_ = true; |
| } |
| } |
| |
| void ClientContext::SendCancelToInterceptors() { |
| internal::CancelInterceptorBatchMethods cancel_methods; |
| for (size_t i = 0; i < rpc_info_.interceptors_.size(); i++) { |
| rpc_info_.RunInterceptor(&cancel_methods, i); |
| } |
| } |
| |
| std::string ClientContext::peer() const { |
| std::string peer; |
| if (call_) { |
| char* c_peer = grpc_call_get_peer(call_); |
| peer = c_peer; |
| gpr_free(c_peer); |
| } |
| return peer; |
| } |
| |
| void ClientContext::SetGlobalCallbacks(GlobalCallbacks* client_callbacks) { |
| GPR_ASSERT(g_client_callbacks == g_default_client_callbacks); |
| GPR_ASSERT(client_callbacks != nullptr); |
| GPR_ASSERT(client_callbacks != g_default_client_callbacks); |
| g_client_callbacks = client_callbacks; |
| } |
| |
| } // namespace grpc |