/*
 *
 * Copyright 2017 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 <grpc/support/alloc.h>
#include <grpc/support/string_util.h>

#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/lb_targets_info.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"

grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
    grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
    grpc_client_channel_factory *client_channel_factory,
    grpc_channel_args *args) {
  grpc_channel_args *new_args = args;
  grpc_channel_credentials *channel_credentials =
      grpc_channel_credentials_find_in_args(args);
  if (channel_credentials != NULL) {
    /* Substitute the channel credentials with a version without call
     * credentials: the load balancer is not necessarily trusted to handle
     * bearer token credentials */
    static const char *keys_to_remove[] = {GRPC_ARG_CHANNEL_CREDENTIALS};
    grpc_channel_credentials *creds_sans_call_creds =
        grpc_channel_credentials_duplicate_without_call_credentials(
            channel_credentials);
    GPR_ASSERT(creds_sans_call_creds != NULL);
    grpc_arg args_to_add[] = {
        grpc_channel_credentials_to_arg(creds_sans_call_creds)};
    /* Create the new set of channel args */
    new_args = grpc_channel_args_copy_and_add_and_remove(
        args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
        GPR_ARRAY_SIZE(args_to_add));
    grpc_channel_credentials_unref(exec_ctx, creds_sans_call_creds);
  }
  grpc_channel *lb_channel = grpc_client_channel_factory_create_channel(
      exec_ctx, client_channel_factory, lb_service_target_addresses,
      GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
  if (channel_credentials != NULL) {
    grpc_channel_args_destroy(exec_ctx, new_args);
  }
  return lb_channel;
}

grpc_channel_args *grpc_lb_policy_grpclb_build_lb_channel_args(
    grpc_exec_ctx *exec_ctx, grpc_slice_hash_table *targets_info,
    grpc_fake_resolver_response_generator *response_generator,
    const grpc_channel_args *args) {
  const grpc_arg to_add[] = {
      grpc_lb_targets_info_create_channel_arg(targets_info),
      grpc_fake_resolver_response_generator_arg(response_generator)};
  /* We remove:
   *
   * - The channel arg for the LB policy name, since we want to use the default
   *   (pick_first) in this case.
   *
   * - The channel arg for the resolved addresses, since that will be generated
   *   by the name resolver used in the LB channel.  Note that the LB channel
   *   will use the fake resolver, so this won't actually generate a query
   *   to DNS (or some other name service).  However, the addresses returned by
   *   the fake resolver will have is_balancer=false, whereas our own
   *   addresses have is_balancer=true.  We need the LB channel to return
   *   addresses with is_balancer=false so that it does not wind up recursively
   *   using the grpclb LB policy, as per the special case logic in
   *   client_channel.c.
   *
   * - The channel arg for the server URI, since that will be different for the
   *   LB channel than for the parent channel (the client channel factory will
   *   re-add this arg with the right value).
   *
   * - The fake resolver generator, because we are replacing it with the one
   *   from the grpclb policy, used to propagate updates to the LB channel. */
  static const char *keys_to_remove[] = {
      GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI,
      GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR};
  /* Add the targets info table to be used for secure naming */
  return grpc_channel_args_copy_and_add_and_remove(
      args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), to_add,
      GPR_ARRAY_SIZE(to_add));
}
