| /* | |
| * | |
| * 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 <grpcpp/client_context.h> | |
| #include <grpc/compression.h> | |
| #include <grpc/grpc.h> | |
| #include <grpc/support/alloc.h> | |
| #include <grpc/support/log.h> | |
| #include <grpc/support/string_util.h> | |
| #include <grpcpp/impl/codegen/interceptor_common.h> | |
| #include <grpcpp/impl/grpc_library.h> | |
| #include <grpcpp/security/credentials.h> | |
| #include <grpcpp/server_context.h> | |
| #include <grpcpp/support/time.h> | |
| namespace grpc { | |
| class DefaultGlobalClientCallbacks final | |
| : public ClientContext::GlobalCallbacks { | |
| public: | |
| ~DefaultGlobalClientCallbacks() override {} | |
| void DefaultConstructor(ClientContext* context) override {} | |
| void Destructor(ClientContext* context) override {} | |
| }; | |
| static internal::GrpcLibraryInitializer g_gli_initializer; | |
| 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), | |
| idempotent_(false), | |
| cacheable_(false), | |
| call_(nullptr), | |
| call_canceled_(false), | |
| deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)), | |
| census_context_(nullptr), | |
| propagate_from_call_(nullptr), | |
| initial_metadata_corked_(false) { | |
| g_client_callbacks->DefaultConstructor(this); | |
| } | |
| ClientContext::~ClientContext() { | |
| if (call_) { | |
| grpc_call_unref(call_); | |
| } | |
| g_client_callbacks->Destructor(this); | |
| } | |
| std::unique_ptr<ClientContext> ClientContext::FromServerContext( | |
| const ServerContext& context, PropagationOptions options) { | |
| std::unique_ptr<ClientContext> ctx(new ClientContext); | |
| ctx->propagate_from_call_ = context.call_; | |
| ctx->propagation_options_ = options; | |
| return ctx; | |
| } | |
| void ClientContext::AddMetadata(const grpc::string& meta_key, | |
| const grpc::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) { | |
| std::unique_lock<std::mutex> 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)) { | |
| gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.", | |
| algorithm); | |
| abort(); | |
| } | |
| GPR_ASSERT(algorithm_name != nullptr); | |
| AddMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name); | |
| } | |
| void ClientContext::TryCancel() { | |
| std::unique_lock<std::mutex> 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); | |
| } | |
| } | |
| grpc::string ClientContext::peer() const { | |
| grpc::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 |