/*
 *
 * Copyright 2018 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/port_platform.h>

#include "src/core/ext/filters/client_channel/resolver_result_parsing.h"

#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.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_registry.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/uri/uri_parser.h"

// As per the retry design, we do not allow more than 5 retry attempts.
#define MAX_MAX_RETRY_ATTEMPTS 5

namespace grpc_core {
namespace internal {

ProcessedResolverResult::ProcessedResolverResult(
    const grpc_channel_args& resolver_result, bool parse_retry) {
  ProcessServiceConfig(resolver_result, parse_retry);
  // If no LB config was found above, just find the LB policy name then.
  if (lb_policy_name_ == nullptr) ProcessLbPolicyName(resolver_result);
}

void ProcessedResolverResult::ProcessServiceConfig(
    const grpc_channel_args& resolver_result, bool parse_retry) {
  const grpc_arg* channel_arg =
      grpc_channel_args_find(&resolver_result, GRPC_ARG_SERVICE_CONFIG);
  const char* service_config_json = grpc_channel_arg_get_string(channel_arg);
  if (service_config_json != nullptr) {
    service_config_json_.reset(gpr_strdup(service_config_json));
    service_config_ = grpc_core::ServiceConfig::Create(service_config_json);
    if (service_config_ != nullptr) {
      if (parse_retry) {
        channel_arg =
            grpc_channel_args_find(&resolver_result, GRPC_ARG_SERVER_URI);
        const char* server_uri = grpc_channel_arg_get_string(channel_arg);
        GPR_ASSERT(server_uri != nullptr);
        grpc_uri* uri = grpc_uri_parse(server_uri, true);
        GPR_ASSERT(uri->path[0] != '\0');
        server_name_ = uri->path[0] == '/' ? uri->path + 1 : uri->path;
        service_config_->ParseGlobalParams(ParseServiceConfig, this);
        grpc_uri_destroy(uri);
      } else {
        service_config_->ParseGlobalParams(ParseServiceConfig, this);
      }
      method_params_table_ = service_config_->CreateMethodConfigTable(
          ClientChannelMethodParams::CreateFromJson);
    }
  }
}

void ProcessedResolverResult::ProcessLbPolicyName(
    const grpc_channel_args& resolver_result) {
  // Prefer the LB policy name found in the service config. Note that this is
  // checking the deprecated loadBalancingPolicy field, rather than the new
  // loadBalancingConfig field.
  if (service_config_ != nullptr) {
    lb_policy_name_.reset(
        gpr_strdup(service_config_->GetLoadBalancingPolicyName()));
    // Convert to lower-case.
    if (lb_policy_name_ != nullptr) {
      char* lb_policy_name = lb_policy_name_.get();
      for (size_t i = 0; i < strlen(lb_policy_name); ++i) {
        lb_policy_name[i] = tolower(lb_policy_name[i]);
      }
    }
  }
  // Otherwise, find the LB policy name set by the client API.
  if (lb_policy_name_ == nullptr) {
    const grpc_arg* channel_arg =
        grpc_channel_args_find(&resolver_result, GRPC_ARG_LB_POLICY_NAME);
    lb_policy_name_.reset(gpr_strdup(grpc_channel_arg_get_string(channel_arg)));
  }
  // Special case: If at least one balancer address is present, we use
  // the grpclb policy, regardless of what the resolver has returned.
  const ServerAddressList* addresses =
      FindServerAddressListChannelArg(&resolver_result);
  if (addresses != nullptr) {
    bool found_balancer_address = false;
    for (size_t i = 0; i < addresses->size(); ++i) {
      const ServerAddress& address = (*addresses)[i];
      if (address.IsBalancer()) {
        found_balancer_address = true;
        break;
      }
    }
    if (found_balancer_address) {
      if (lb_policy_name_ != nullptr &&
          strcmp(lb_policy_name_.get(), "grpclb") != 0) {
        gpr_log(GPR_INFO,
                "resolver requested LB policy %s but provided at least one "
                "balancer address -- forcing use of grpclb LB policy",
                lb_policy_name_.get());
      }
      lb_policy_name_.reset(gpr_strdup("grpclb"));
    }
  }
  // Use pick_first if nothing was specified and we didn't select grpclb
  // above.
  if (lb_policy_name_ == nullptr) {
    lb_policy_name_.reset(gpr_strdup("pick_first"));
  }
}

void ProcessedResolverResult::ParseServiceConfig(
    const grpc_json* field, ProcessedResolverResult* parsing_state) {
  parsing_state->ParseLbConfigFromServiceConfig(field);
  if (parsing_state->server_name_ != nullptr) {
    parsing_state->ParseRetryThrottleParamsFromServiceConfig(field);
  }
}

void ProcessedResolverResult::ParseLbConfigFromServiceConfig(
    const grpc_json* field) {
  if (lb_policy_config_ != nullptr) return;  // Already found.
  // Find the LB config global parameter.
  if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0 ||
      field->type != GRPC_JSON_ARRAY) {
    return;  // Not valid lb config array.
  }
  // Find the first LB policy that this client supports.
  for (grpc_json* lb_config = field->child; lb_config != nullptr;
       lb_config = lb_config->next) {
    if (lb_config->type != GRPC_JSON_OBJECT) return;
    // Find the policy object.
    grpc_json* policy = nullptr;
    for (grpc_json* field = lb_config->child; field != nullptr;
         field = field->next) {
      if (field->key == nullptr || strcmp(field->key, "policy") != 0 ||
          field->type != GRPC_JSON_OBJECT) {
        return;
      }
      if (policy != nullptr) return;  // Duplicate.
      policy = field;
    }
    // Find the specific policy content since the policy object is of type
    // "oneof".
    grpc_json* policy_content = nullptr;
    for (grpc_json* field = policy->child; field != nullptr;
         field = field->next) {
      if (field->key == nullptr || field->type != GRPC_JSON_OBJECT) return;
      if (policy_content != nullptr) return;  // Violate "oneof" type.
      policy_content = field;
    }
    // If we support this policy, then select it.
    if (grpc_core::LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(
            policy_content->key)) {
      lb_policy_name_.reset(gpr_strdup(policy_content->key));
      lb_policy_config_ = policy_content->child;
      return;
    }
  }
}

void ProcessedResolverResult::ParseRetryThrottleParamsFromServiceConfig(
    const grpc_json* field) {
  if (strcmp(field->key, "retryThrottling") == 0) {
    if (retry_throttle_data_ != nullptr) return;  // Duplicate.
    if (field->type != GRPC_JSON_OBJECT) return;
    int max_milli_tokens = 0;
    int milli_token_ratio = 0;
    for (grpc_json* sub_field = field->child; sub_field != nullptr;
         sub_field = sub_field->next) {
      if (sub_field->key == nullptr) return;
      if (strcmp(sub_field->key, "maxTokens") == 0) {
        if (max_milli_tokens != 0) return;  // Duplicate.
        if (sub_field->type != GRPC_JSON_NUMBER) return;
        max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
        if (max_milli_tokens == -1) return;
        max_milli_tokens *= 1000;
      } else if (strcmp(sub_field->key, "tokenRatio") == 0) {
        if (milli_token_ratio != 0) return;  // Duplicate.
        if (sub_field->type != GRPC_JSON_NUMBER) return;
        // We support up to 3 decimal digits.
        size_t whole_len = strlen(sub_field->value);
        uint32_t multiplier = 1;
        uint32_t decimal_value = 0;
        const char* decimal_point = strchr(sub_field->value, '.');
        if (decimal_point != nullptr) {
          whole_len = static_cast<size_t>(decimal_point - sub_field->value);
          multiplier = 1000;
          size_t decimal_len = strlen(decimal_point + 1);
          if (decimal_len > 3) decimal_len = 3;
          if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
                                         &decimal_value)) {
            return;
          }
          uint32_t decimal_multiplier = 1;
          for (size_t i = 0; i < (3 - decimal_len); ++i) {
            decimal_multiplier *= 10;
          }
          decimal_value *= decimal_multiplier;
        }
        uint32_t whole_value;
        if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
                                       &whole_value)) {
          return;
        }
        milli_token_ratio =
            static_cast<int>((whole_value * multiplier) + decimal_value);
        if (milli_token_ratio <= 0) return;
      }
    }
    retry_throttle_data_ =
        grpc_core::internal::ServerRetryThrottleMap::GetDataForServer(
            server_name_, max_milli_tokens, milli_token_ratio);
  }
}

namespace {

bool ParseWaitForReady(
    grpc_json* field, ClientChannelMethodParams::WaitForReady* wait_for_ready) {
  if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
    return false;
  }
  *wait_for_ready = field->type == GRPC_JSON_TRUE
                        ? ClientChannelMethodParams::WAIT_FOR_READY_TRUE
                        : ClientChannelMethodParams::WAIT_FOR_READY_FALSE;
  return true;
}

// Parses a JSON field of the form generated for a google.proto.Duration
// proto message, as per:
//   https://developers.google.com/protocol-buffers/docs/proto3#json
bool ParseDuration(grpc_json* field, grpc_millis* duration) {
  if (field->type != GRPC_JSON_STRING) return false;
  size_t len = strlen(field->value);
  if (field->value[len - 1] != 's') return false;
  UniquePtr<char> buf(gpr_strdup(field->value));
  *(buf.get() + len - 1) = '\0';  // Remove trailing 's'.
  char* decimal_point = strchr(buf.get(), '.');
  int nanos = 0;
  if (decimal_point != nullptr) {
    *decimal_point = '\0';
    nanos = gpr_parse_nonnegative_int(decimal_point + 1);
    if (nanos == -1) {
      return false;
    }
    int num_digits = static_cast<int>(strlen(decimal_point + 1));
    if (num_digits > 9) {  // We don't accept greater precision than nanos.
      return false;
    }
    for (int i = 0; i < (9 - num_digits); ++i) {
      nanos *= 10;
    }
  }
  int seconds =
      decimal_point == buf.get() ? 0 : gpr_parse_nonnegative_int(buf.get());
  if (seconds == -1) return false;
  *duration = seconds * GPR_MS_PER_SEC + nanos / GPR_NS_PER_MS;
  return true;
}

UniquePtr<ClientChannelMethodParams::RetryPolicy> ParseRetryPolicy(
    grpc_json* field) {
  auto retry_policy = MakeUnique<ClientChannelMethodParams::RetryPolicy>();
  if (field->type != GRPC_JSON_OBJECT) return nullptr;
  for (grpc_json* sub_field = field->child; sub_field != nullptr;
       sub_field = sub_field->next) {
    if (sub_field->key == nullptr) return nullptr;
    if (strcmp(sub_field->key, "maxAttempts") == 0) {
      if (retry_policy->max_attempts != 0) return nullptr;  // Duplicate.
      if (sub_field->type != GRPC_JSON_NUMBER) return nullptr;
      retry_policy->max_attempts = gpr_parse_nonnegative_int(sub_field->value);
      if (retry_policy->max_attempts <= 1) return nullptr;
      if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) {
        gpr_log(GPR_ERROR,
                "service config: clamped retryPolicy.maxAttempts at %d",
                MAX_MAX_RETRY_ATTEMPTS);
        retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS;
      }
    } else if (strcmp(sub_field->key, "initialBackoff") == 0) {
      if (retry_policy->initial_backoff > 0) return nullptr;  // Duplicate.
      if (!ParseDuration(sub_field, &retry_policy->initial_backoff)) {
        return nullptr;
      }
      if (retry_policy->initial_backoff == 0) return nullptr;
    } else if (strcmp(sub_field->key, "maxBackoff") == 0) {
      if (retry_policy->max_backoff > 0) return nullptr;  // Duplicate.
      if (!ParseDuration(sub_field, &retry_policy->max_backoff)) {
        return nullptr;
      }
      if (retry_policy->max_backoff == 0) return nullptr;
    } else if (strcmp(sub_field->key, "backoffMultiplier") == 0) {
      if (retry_policy->backoff_multiplier != 0) return nullptr;  // Duplicate.
      if (sub_field->type != GRPC_JSON_NUMBER) return nullptr;
      if (sscanf(sub_field->value, "%f", &retry_policy->backoff_multiplier) !=
          1) {
        return nullptr;
      }
      if (retry_policy->backoff_multiplier <= 0) return nullptr;
    } else if (strcmp(sub_field->key, "retryableStatusCodes") == 0) {
      if (!retry_policy->retryable_status_codes.Empty()) {
        return nullptr;  // Duplicate.
      }
      if (sub_field->type != GRPC_JSON_ARRAY) return nullptr;
      for (grpc_json* element = sub_field->child; element != nullptr;
           element = element->next) {
        if (element->type != GRPC_JSON_STRING) return nullptr;
        grpc_status_code status;
        if (!grpc_status_code_from_string(element->value, &status)) {
          return nullptr;
        }
        retry_policy->retryable_status_codes.Add(status);
      }
      if (retry_policy->retryable_status_codes.Empty()) return nullptr;
    }
  }
  // Make sure required fields are set.
  if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 ||
      retry_policy->max_backoff == 0 || retry_policy->backoff_multiplier == 0 ||
      retry_policy->retryable_status_codes.Empty()) {
    return nullptr;
  }
  return retry_policy;
}

}  // namespace

RefCountedPtr<ClientChannelMethodParams>
ClientChannelMethodParams::CreateFromJson(const grpc_json* json) {
  RefCountedPtr<ClientChannelMethodParams> method_params =
      MakeRefCounted<ClientChannelMethodParams>();
  for (grpc_json* field = json->child; field != nullptr; field = field->next) {
    if (field->key == nullptr) continue;
    if (strcmp(field->key, "waitForReady") == 0) {
      if (method_params->wait_for_ready_ != WAIT_FOR_READY_UNSET) {
        return nullptr;  // Duplicate.
      }
      if (!ParseWaitForReady(field, &method_params->wait_for_ready_)) {
        return nullptr;
      }
    } else if (strcmp(field->key, "timeout") == 0) {
      if (method_params->timeout_ > 0) return nullptr;  // Duplicate.
      if (!ParseDuration(field, &method_params->timeout_)) return nullptr;
    } else if (strcmp(field->key, "retryPolicy") == 0) {
      if (method_params->retry_policy_ != nullptr) {
        return nullptr;  // Duplicate.
      }
      method_params->retry_policy_ = ParseRetryPolicy(field);
      if (method_params->retry_policy_ == nullptr) return nullptr;
    }
  }
  return method_params;
}

}  // namespace internal
}  // namespace grpc_core
