Home | History | Annotate | Download | only in common
      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 <grpcpp/support/channel_arguments.h>
     19 
     20 #include <sstream>
     21 
     22 #include <grpc/impl/codegen/grpc_types.h>
     23 #include <grpc/support/log.h>
     24 #include <grpcpp/grpcpp.h>
     25 #include <grpcpp/resource_quota.h>
     26 #include "src/core/lib/channel/channel_args.h"
     27 #include "src/core/lib/iomgr/exec_ctx.h"
     28 #include "src/core/lib/iomgr/socket_mutator.h"
     29 
     30 namespace grpc {
     31 
     32 ChannelArguments::ChannelArguments() {
     33   // This will be ignored if used on the server side.
     34   SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING, "grpc-c++/" + Version());
     35 }
     36 
     37 ChannelArguments::ChannelArguments(const ChannelArguments& other)
     38     : strings_(other.strings_) {
     39   args_.reserve(other.args_.size());
     40   auto list_it_dst = strings_.begin();
     41   auto list_it_src = other.strings_.begin();
     42   for (auto a = other.args_.begin(); a != other.args_.end(); ++a) {
     43     grpc_arg ap;
     44     ap.type = a->type;
     45     GPR_ASSERT(list_it_src->c_str() == a->key);
     46     ap.key = const_cast<char*>(list_it_dst->c_str());
     47     ++list_it_src;
     48     ++list_it_dst;
     49     switch (a->type) {
     50       case GRPC_ARG_INTEGER:
     51         ap.value.integer = a->value.integer;
     52         break;
     53       case GRPC_ARG_STRING:
     54         GPR_ASSERT(list_it_src->c_str() == a->value.string);
     55         ap.value.string = const_cast<char*>(list_it_dst->c_str());
     56         ++list_it_src;
     57         ++list_it_dst;
     58         break;
     59       case GRPC_ARG_POINTER:
     60         ap.value.pointer = a->value.pointer;
     61         ap.value.pointer.p = a->value.pointer.vtable->copy(ap.value.pointer.p);
     62         break;
     63     }
     64     args_.push_back(ap);
     65   }
     66 }
     67 
     68 ChannelArguments::~ChannelArguments() {
     69   grpc_core::ExecCtx exec_ctx;
     70   for (auto it = args_.begin(); it != args_.end(); ++it) {
     71     if (it->type == GRPC_ARG_POINTER) {
     72       it->value.pointer.vtable->destroy(it->value.pointer.p);
     73     }
     74   }
     75 }
     76 
     77 void ChannelArguments::Swap(ChannelArguments& other) {
     78   args_.swap(other.args_);
     79   strings_.swap(other.strings_);
     80 }
     81 
     82 void ChannelArguments::SetCompressionAlgorithm(
     83     grpc_compression_algorithm algorithm) {
     84   SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm);
     85 }
     86 
     87 void ChannelArguments::SetGrpclbFallbackTimeout(int fallback_timeout) {
     88   SetInt(GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS, fallback_timeout);
     89 }
     90 
     91 void ChannelArguments::SetSocketMutator(grpc_socket_mutator* mutator) {
     92   if (!mutator) {
     93     return;
     94   }
     95   grpc_arg mutator_arg = grpc_socket_mutator_to_arg(mutator);
     96   bool replaced = false;
     97   grpc_core::ExecCtx exec_ctx;
     98   for (auto it = args_.begin(); it != args_.end(); ++it) {
     99     if (it->type == mutator_arg.type &&
    100         grpc::string(it->key) == grpc::string(mutator_arg.key)) {
    101       GPR_ASSERT(!replaced);
    102       it->value.pointer.vtable->destroy(it->value.pointer.p);
    103       it->value.pointer = mutator_arg.value.pointer;
    104       replaced = true;
    105     }
    106   }
    107 
    108   if (!replaced) {
    109     args_.push_back(mutator_arg);
    110   }
    111 }
    112 
    113 // Note: a second call to this will add in front the result of the first call.
    114 // An example is calling this on a copy of ChannelArguments which already has a
    115 // prefix. The user can build up a prefix string by calling this multiple times,
    116 // each with more significant identifier.
    117 void ChannelArguments::SetUserAgentPrefix(
    118     const grpc::string& user_agent_prefix) {
    119   if (user_agent_prefix.empty()) {
    120     return;
    121   }
    122   bool replaced = false;
    123   auto strings_it = strings_.begin();
    124   for (auto it = args_.begin(); it != args_.end(); ++it) {
    125     const grpc_arg& arg = *it;
    126     ++strings_it;
    127     if (arg.type == GRPC_ARG_STRING) {
    128       if (grpc::string(arg.key) == GRPC_ARG_PRIMARY_USER_AGENT_STRING) {
    129         GPR_ASSERT(arg.value.string == strings_it->c_str());
    130         *(strings_it) = user_agent_prefix + " " + arg.value.string;
    131         it->value.string = const_cast<char*>(strings_it->c_str());
    132         replaced = true;
    133         break;
    134       }
    135       ++strings_it;
    136     }
    137   }
    138   if (!replaced) {
    139     SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING, user_agent_prefix);
    140   }
    141 }
    142 
    143 void ChannelArguments::SetResourceQuota(
    144     const grpc::ResourceQuota& resource_quota) {
    145   SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA,
    146                        resource_quota.c_resource_quota(),
    147                        grpc_resource_quota_arg_vtable());
    148 }
    149 
    150 void ChannelArguments::SetMaxReceiveMessageSize(int size) {
    151   SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, size);
    152 }
    153 
    154 void ChannelArguments::SetMaxSendMessageSize(int size) {
    155   SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, size);
    156 }
    157 
    158 void ChannelArguments::SetLoadBalancingPolicyName(
    159     const grpc::string& lb_policy_name) {
    160   SetString(GRPC_ARG_LB_POLICY_NAME, lb_policy_name);
    161 }
    162 
    163 void ChannelArguments::SetServiceConfigJSON(
    164     const grpc::string& service_config_json) {
    165   SetString(GRPC_ARG_SERVICE_CONFIG, service_config_json);
    166 }
    167 
    168 void ChannelArguments::SetInt(const grpc::string& key, int value) {
    169   grpc_arg arg;
    170   arg.type = GRPC_ARG_INTEGER;
    171   strings_.push_back(key);
    172   arg.key = const_cast<char*>(strings_.back().c_str());
    173   arg.value.integer = value;
    174 
    175   args_.push_back(arg);
    176 }
    177 
    178 void ChannelArguments::SetPointer(const grpc::string& key, void* value) {
    179   static const grpc_arg_pointer_vtable vtable = {
    180       &PointerVtableMembers::Copy, &PointerVtableMembers::Destroy,
    181       &PointerVtableMembers::Compare};
    182   SetPointerWithVtable(key, value, &vtable);
    183 }
    184 
    185 void ChannelArguments::SetPointerWithVtable(
    186     const grpc::string& key, void* value,
    187     const grpc_arg_pointer_vtable* vtable) {
    188   grpc_arg arg;
    189   arg.type = GRPC_ARG_POINTER;
    190   strings_.push_back(key);
    191   arg.key = const_cast<char*>(strings_.back().c_str());
    192   arg.value.pointer.p = vtable->copy(value);
    193   arg.value.pointer.vtable = vtable;
    194   args_.push_back(arg);
    195 }
    196 
    197 void ChannelArguments::SetString(const grpc::string& key,
    198                                  const grpc::string& value) {
    199   grpc_arg arg;
    200   arg.type = GRPC_ARG_STRING;
    201   strings_.push_back(key);
    202   arg.key = const_cast<char*>(strings_.back().c_str());
    203   strings_.push_back(value);
    204   arg.value.string = const_cast<char*>(strings_.back().c_str());
    205 
    206   args_.push_back(arg);
    207 }
    208 
    209 void ChannelArguments::SetChannelArgs(grpc_channel_args* channel_args) const {
    210   channel_args->num_args = args_.size();
    211   if (channel_args->num_args > 0) {
    212     channel_args->args = const_cast<grpc_arg*>(&args_[0]);
    213   }
    214 }
    215 
    216 }  // namespace grpc
    217