// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/dns/host_resolver_internal_result.h"

#include <map>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include "base/check_op.h"
#include "base/json/values_util.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/connection_endpoint_metadata.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/dns/https_record_rdata.h"
#include "net/dns/public/dns_query_type.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/url_canon.h"
#include "url/url_canon_stdstring.h"

namespace net {

namespace {

// base::Value keys
constexpr base::StringPiece kValueDomainNameKey = "domain_name";
constexpr base::StringPiece kValueQueryTypeKey = "query_type";
constexpr base::StringPiece kValueTypeKey = "type";
constexpr base::StringPiece kValueSourceKey = "source";
constexpr base::StringPiece kValueTimedExpirationKey = "timed_expiration";
constexpr base::StringPiece kValueEndpointsKey = "endpoints";
constexpr base::StringPiece kValueStringsKey = "strings";
constexpr base::StringPiece kValueHostsKey = "hosts";
constexpr base::StringPiece kValueMetadatasKey = "metadatas";
constexpr base::StringPiece kValueMetadataWeightKey = "metadata_weight";
constexpr base::StringPiece kValueMetadataValueKey = "metadata_value";
constexpr base::StringPiece kValueErrorKey = "error";
constexpr base::StringPiece kValueAliasTargetKey = "alias_target";

// Returns `domain_name` as-is if it could not be canonicalized.
std::string MaybeCanonicalizeName(std::string domain_name) {
  std::string canonicalized;
  url::StdStringCanonOutput output(&canonicalized);
  url::CanonHostInfo host_info;

  url::CanonicalizeHostVerbose(domain_name.data(),
                               url::Component(0, domain_name.size()), &output,
                               &host_info);

  if (host_info.family == url::CanonHostInfo::Family::NEUTRAL) {
    output.Complete();
    return canonicalized;
  } else {
    return domain_name;
  }
}

base::Value EndpointMetadataPairToValue(
    const std::pair<HttpsRecordPriority, ConnectionEndpointMetadata>& pair) {
  base::Value::Dict dictionary;
  dictionary.Set(kValueMetadataWeightKey, pair.first);
  dictionary.Set(kValueMetadataValueKey, pair.second.ToValue());
  return base::Value(std::move(dictionary));
}

absl::optional<std::pair<HttpsRecordPriority, ConnectionEndpointMetadata>>
EndpointMetadataPairFromValue(const base::Value& value) {
  const base::Value::Dict* dict = value.GetIfDict();
  if (!dict)
    return absl::nullopt;

  absl::optional<int> weight = dict->FindInt(kValueMetadataWeightKey);
  if (!weight || !base::IsValueInRangeForNumericType<HttpsRecordPriority>(
                     weight.value())) {
    return absl::nullopt;
  }

  const base::Value* metadata_value = dict->Find(kValueMetadataValueKey);
  if (!metadata_value)
    return absl::nullopt;
  absl::optional<ConnectionEndpointMetadata> metadata =
      ConnectionEndpointMetadata::FromValue(*metadata_value);
  if (!metadata)
    return absl::nullopt;

  return std::make_pair(base::checked_cast<HttpsRecordPriority>(weight.value()),
                        std::move(metadata).value());
}

absl::optional<DnsQueryType> QueryTypeFromValue(const base::Value& value) {
  const std::string* query_type_string = value.GetIfString();
  if (!query_type_string)
    return absl::nullopt;
/* Cobalt
  const auto* query_type_it =
Cobalt */
  const auto query_type_it =
      base::ranges::find(kDnsQueryTypes, *query_type_string,
                         &decltype(kDnsQueryTypes)::value_type::second);
  if (query_type_it == kDnsQueryTypes.end())
    return absl::nullopt;

  return query_type_it->first;
}

base::Value TypeToValue(HostResolverInternalResult::Type type) {
  switch (type) {
    case HostResolverInternalResult::Type::kData:
      return base::Value("data");
    case HostResolverInternalResult::Type::kMetadata:
      return base::Value("metadata");
    case HostResolverInternalResult::Type::kError:
      return base::Value("error");
    case HostResolverInternalResult::Type::kAlias:
      return base::Value("alias");
  }
}

absl::optional<HostResolverInternalResult::Type> TypeFromValue(
    const base::Value& value) {
  const std::string* string = value.GetIfString();
  if (!string)
    return absl::nullopt;

  if (*string == "data") {
    return HostResolverInternalResult::Type::kData;
  } else if (*string == "metadata") {
    return HostResolverInternalResult::Type::kMetadata;
  } else if (*string == "error") {
    return HostResolverInternalResult::Type::kError;
  } else if (*string == "alias") {
    return HostResolverInternalResult::Type::kAlias;
  } else {
    return absl::nullopt;
  }
}

base::Value SourceToValue(HostResolverInternalResult::Source source) {
  switch (source) {
    case HostResolverInternalResult::Source::kDns:
      return base::Value("dns");
    case HostResolverInternalResult::Source::kHosts:
      return base::Value("hosts");
    case HostResolverInternalResult::Source::kUnknown:
      return base::Value("unknown");
  }
}

absl::optional<HostResolverInternalResult::Source> SourceFromValue(
    const base::Value& value) {
  const std::string* string = value.GetIfString();
  if (!string)
    return absl::nullopt;

  if (*string == "dns") {
    return HostResolverInternalResult::Source::kDns;
  } else if (*string == "hosts") {
    return HostResolverInternalResult::Source::kHosts;
  } else if (*string == "unknown") {
    return HostResolverInternalResult::Source::kUnknown;
  } else {
    return absl::nullopt;
  }
}

}  // namespace

// static
std::unique_ptr<HostResolverInternalResult>
HostResolverInternalResult::FromValue(const base::Value& value) {
  const base::Value::Dict* dict = value.GetIfDict();
  if (!dict)
    return nullptr;

  const base::Value* type_value = dict->Find(kValueTypeKey);
  if (!type_value)
    return nullptr;
  absl::optional<Type> type = TypeFromValue(*type_value);
  if (!type.has_value())
    return nullptr;

  switch (type.value()) {
    case Type::kData:
      return HostResolverInternalDataResult::FromValue(value);
    case Type::kMetadata:
      return HostResolverInternalMetadataResult::FromValue(value);
    case Type::kError:
      return HostResolverInternalErrorResult::FromValue(value);
    case Type::kAlias:
      return HostResolverInternalAliasResult::FromValue(value);
  }
}

const HostResolverInternalDataResult& HostResolverInternalResult::AsData()
    const {
  CHECK_EQ(type_, Type::kData);
  return *static_cast<const HostResolverInternalDataResult*>(this);
}

const HostResolverInternalMetadataResult&
HostResolverInternalResult::AsMetadata() const {
  CHECK_EQ(type_, Type::kMetadata);
  return *static_cast<const HostResolverInternalMetadataResult*>(this);
}

const HostResolverInternalErrorResult& HostResolverInternalResult::AsError()
    const {
  CHECK_EQ(type_, Type::kError);
  return *static_cast<const HostResolverInternalErrorResult*>(this);
}

const HostResolverInternalAliasResult& HostResolverInternalResult::AsAlias()
    const {
  CHECK_EQ(type_, Type::kAlias);
  return *static_cast<const HostResolverInternalAliasResult*>(this);
}

HostResolverInternalResult::HostResolverInternalResult(
    std::string domain_name,
    DnsQueryType query_type,
    absl::optional<base::TimeTicks> expiration,
    absl::optional<base::Time> timed_expiration,
    Type type,
    Source source)
    : domain_name_(MaybeCanonicalizeName(std::move(domain_name))),
      query_type_(query_type),
      type_(type),
      source_(source),
      expiration_(expiration),
      timed_expiration_(timed_expiration) {
  DCHECK(!domain_name_.empty());
  // If `expiration` has a value, `timed_expiration` must too.
  DCHECK(!expiration_.has_value() || timed_expiration.has_value());
}

HostResolverInternalResult::HostResolverInternalResult(
    const base::Value::Dict& dict)
    : domain_name_(*dict.FindString(kValueDomainNameKey)),
      query_type_(QueryTypeFromValue(*dict.Find(kValueQueryTypeKey)).value()),
      type_(TypeFromValue(*dict.Find(kValueTypeKey)).value()),
      source_(SourceFromValue(*dict.Find(kValueSourceKey)).value()),
      timed_expiration_(
          dict.contains(kValueTimedExpirationKey)
              ? base::ValueToTime(*dict.Find(kValueTimedExpirationKey))
              : absl::optional<base::Time>()) {}

// static
bool HostResolverInternalResult::ValidateValueBaseDict(
    const base::Value::Dict& dict,
    bool require_timed_expiration) {
  const std::string* domain_name = dict.FindString(kValueDomainNameKey);
  if (!domain_name)
    return false;

  const std::string* query_type_string = dict.FindString(kValueQueryTypeKey);
  if (!query_type_string)
    return false;
/* Cobalt
  const auto* query_type_it =
Cobalt */
  const auto query_type_it =
      base::ranges::find(kDnsQueryTypes, *query_type_string,
                         &decltype(kDnsQueryTypes)::value_type::second);
  if (query_type_it == kDnsQueryTypes.end())
    return false;

  const base::Value* type_value = dict.Find(kValueTypeKey);
  if (!type_value)
    return false;
  absl::optional<Type> type = TypeFromValue(*type_value);
  if (!type.has_value())
    return false;

  const base::Value* source_value = dict.Find(kValueSourceKey);
  if (!source_value)
    return false;
  absl::optional<Source> source = SourceFromValue(*source_value);
  if (!source.has_value())
    return false;

  absl::optional<base::Time> timed_expiration;
  const base::Value* timed_expiration_value =
      dict.Find(kValueTimedExpirationKey);
  if (require_timed_expiration && !timed_expiration_value)
    return false;
  if (timed_expiration_value) {
    timed_expiration = base::ValueToTime(timed_expiration_value);
    if (!timed_expiration.has_value())
      return false;
  }

  return true;
}

base::Value::Dict HostResolverInternalResult::ToValueBaseDict() const {
  base::Value::Dict dict;

  dict.Set(kValueDomainNameKey, domain_name_);
  dict.Set(kValueQueryTypeKey, kDnsQueryTypes.at(query_type_));
  dict.Set(kValueTypeKey, TypeToValue(type_));
  dict.Set(kValueSourceKey, SourceToValue(source_));

  // `expiration_` is not serialized because it is TimeTicks.

  if (timed_expiration_.has_value()) {
    dict.Set(kValueTimedExpirationKey,
             base::TimeToValue(timed_expiration_.value()));
  }

  return dict;
}

// static
std::unique_ptr<HostResolverInternalDataResult>
HostResolverInternalDataResult::FromValue(const base::Value& value) {
  const base::Value::Dict* dict = value.GetIfDict();
  if (!dict || !ValidateValueBaseDict(*dict, /*require_timed_expiration=*/true))
    return nullptr;

  const base::Value::List* endpoint_values = dict->FindList(kValueEndpointsKey);
  if (!endpoint_values)
    return nullptr;

  std::vector<IPEndPoint> endpoints;
  endpoints.reserve(endpoint_values->size());
  for (const base::Value& endpoint_value : *endpoint_values) {
    absl::optional<IPEndPoint> endpoint = IPEndPoint::FromValue(endpoint_value);
    if (!endpoint.has_value())
      return nullptr;

    endpoints.push_back(std::move(endpoint).value());
  }

  const base::Value::List* string_values = dict->FindList(kValueStringsKey);
  if (!string_values)
    return nullptr;

  std::vector<std::string> strings;
  strings.reserve(string_values->size());
  for (const base::Value& string_value : *string_values) {
    const std::string* string = string_value.GetIfString();
    if (!string)
      return nullptr;

    strings.push_back(*string);
  }

  const base::Value::List* host_values = dict->FindList(kValueHostsKey);
  if (!host_values)
    return nullptr;

  std::vector<HostPortPair> hosts;
  hosts.reserve(host_values->size());
  for (const base::Value& host_value : *host_values) {
    absl::optional<HostPortPair> host = HostPortPair::FromValue(host_value);
    if (!host.has_value())
      return nullptr;

    hosts.push_back(std::move(host).value());
  }

  // WrapUnique due to private constructor.
  return base::WrapUnique(new HostResolverInternalDataResult(
      *dict, std::move(endpoints), std::move(strings), std::move(hosts)));
}

HostResolverInternalDataResult::HostResolverInternalDataResult(
    std::string domain_name,
    DnsQueryType query_type,
    absl::optional<base::TimeTicks> expiration,
    base::Time timed_expiration,
    Source source,
    std::vector<IPEndPoint> endpoints,
    std::vector<std::string> strings,
    std::vector<HostPortPair> hosts)
    : HostResolverInternalResult(std::move(domain_name),
                                 query_type,
                                 expiration,
                                 timed_expiration,
                                 Type::kData,
                                 source),
      endpoints_(std::move(endpoints)),
      strings_(std::move(strings)),
      hosts_(std::move(hosts)) {
  DCHECK(!endpoints_.empty() || !strings_.empty() || !hosts_.empty());
}

HostResolverInternalDataResult::~HostResolverInternalDataResult() = default;

base::Value HostResolverInternalDataResult::ToValue() const {
  base::Value::Dict dict = ToValueBaseDict();

  base::Value::List endpoints_list;
  endpoints_list.reserve(endpoints_.size());
  for (IPEndPoint endpoint : endpoints_) {
    endpoints_list.Append(endpoint.ToValue());
  }
  dict.Set(kValueEndpointsKey, std::move(endpoints_list));

  base::Value::List strings_list;
  strings_list.reserve(strings_.size());
  for (const std::string& string : strings_) {
    strings_list.Append(string);
  }
  dict.Set(kValueStringsKey, std::move(strings_list));

  base::Value::List hosts_list;
  hosts_list.reserve(hosts_.size());
  for (const HostPortPair& host : hosts_) {
    hosts_list.Append(host.ToValue());
  }
  dict.Set(kValueHostsKey, std::move(hosts_list));

  return base::Value(std::move(dict));
}

HostResolverInternalDataResult::HostResolverInternalDataResult(
    const base::Value::Dict& dict,
    std::vector<IPEndPoint> endpoints,
    std::vector<std::string> strings,
    std::vector<HostPortPair> hosts)
    : HostResolverInternalResult(dict),
      endpoints_(std::move(endpoints)),
      strings_(std::move(strings)),
      hosts_(std::move(hosts)) {}

// static
std::unique_ptr<HostResolverInternalMetadataResult>
HostResolverInternalMetadataResult::FromValue(const base::Value& value) {
  const base::Value::Dict* dict = value.GetIfDict();
  if (!dict || !ValidateValueBaseDict(*dict, /*require_timed_expiration=*/true))
    return nullptr;

  const base::Value::List* metadata_values = dict->FindList(kValueMetadatasKey);
  if (!metadata_values)
    return nullptr;

  std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas;
  for (const base::Value& metadata_value : *metadata_values) {
    absl::optional<std::pair<HttpsRecordPriority, ConnectionEndpointMetadata>>
        metadata = EndpointMetadataPairFromValue(metadata_value);
    if (!metadata.has_value())
      return nullptr;
    metadatas.insert(std::move(metadata).value());
  }

  // WrapUnique due to private constructor.
  return base::WrapUnique(
      new HostResolverInternalMetadataResult(*dict, std::move(metadatas)));
}

HostResolverInternalMetadataResult::HostResolverInternalMetadataResult(
    std::string domain_name,
    DnsQueryType query_type,
    absl::optional<base::TimeTicks> expiration,
    base::Time timed_expiration,
    Source source,
    std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas)
    : HostResolverInternalResult(std::move(domain_name),
                                 query_type,
                                 expiration,
                                 timed_expiration,
                                 Type::kMetadata,
                                 source),
      metadatas_(std::move(metadatas)) {}

HostResolverInternalMetadataResult::~HostResolverInternalMetadataResult() =
    default;

base::Value HostResolverInternalMetadataResult::ToValue() const {
  base::Value::Dict dict = ToValueBaseDict();

  base::Value::List metadatas_list;
  metadatas_list.reserve(metadatas_.size());
  for (const std::pair<const HttpsRecordPriority, ConnectionEndpointMetadata>&
           metadata_pair : metadatas_) {
    metadatas_list.Append(EndpointMetadataPairToValue(metadata_pair));
  }
  dict.Set(kValueMetadatasKey, std::move(metadatas_list));

  return base::Value(std::move(dict));
}

HostResolverInternalMetadataResult::HostResolverInternalMetadataResult(
    const base::Value::Dict& dict,
    std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas)
    : HostResolverInternalResult(dict), metadatas_(std::move(metadatas)) {}

// static
std::unique_ptr<HostResolverInternalErrorResult>
HostResolverInternalErrorResult::FromValue(const base::Value& value) {
  const base::Value::Dict* dict = value.GetIfDict();
  if (!dict ||
      !ValidateValueBaseDict(*dict, /*require_timed_expiration=*/false)) {
    return nullptr;
  }

  absl::optional<int> error = dict->FindInt(kValueErrorKey);
  if (!error.has_value())
    return nullptr;

  // WrapUnique due to private constructor.
  return base::WrapUnique(
      new HostResolverInternalErrorResult(*dict, error.value()));
}

HostResolverInternalErrorResult::HostResolverInternalErrorResult(
    std::string domain_name,
    DnsQueryType query_type,
    absl::optional<base::TimeTicks> expiration,
    absl::optional<base::Time> timed_expiration,
    Source source,
    int error)
    : HostResolverInternalResult(std::move(domain_name),
                                 query_type,
                                 expiration,
                                 timed_expiration,
                                 Type::kError,
                                 source),
      error_(error) {}

base::Value HostResolverInternalErrorResult::ToValue() const {
  base::Value::Dict dict = ToValueBaseDict();

  dict.Set(kValueErrorKey, error_);

  return base::Value(std::move(dict));
}

HostResolverInternalErrorResult::HostResolverInternalErrorResult(
    const base::Value::Dict& dict,
    int error)
    : HostResolverInternalResult(dict), error_(error) {
  DCHECK_NE(error_, OK);
}

// static
std::unique_ptr<HostResolverInternalAliasResult>
HostResolverInternalAliasResult::FromValue(const base::Value& value) {
  const base::Value::Dict* dict = value.GetIfDict();
  if (!dict || !ValidateValueBaseDict(*dict, /*require_timed_expiration=*/true))
    return nullptr;

  const std::string* target = dict->FindString(kValueAliasTargetKey);
  if (!target)
    return nullptr;

  // WrapUnique due to private constructor.
  return base::WrapUnique(new HostResolverInternalAliasResult(*dict, *target));
}

HostResolverInternalAliasResult::HostResolverInternalAliasResult(
    std::string domain_name,
    DnsQueryType query_type,
    absl::optional<base::TimeTicks> expiration,
    base::Time timed_expiration,
    Source source,
    std::string alias_target)
    : HostResolverInternalResult(std::move(domain_name),
                                 query_type,
                                 expiration,
                                 timed_expiration,
                                 Type::kAlias,
                                 source),
      alias_target_(MaybeCanonicalizeName(std::move(alias_target))) {
  DCHECK(!alias_target_.empty());
}

base::Value HostResolverInternalAliasResult::ToValue() const {
  base::Value::Dict dict = ToValueBaseDict();

  dict.Set(kValueAliasTargetKey, alias_target_);

  return base::Value(std::move(dict));
}

HostResolverInternalAliasResult::HostResolverInternalAliasResult(
    const base::Value::Dict& dict,
    std::string alias_target)
    : HostResolverInternalResult(dict),
      alias_target_(MaybeCanonicalizeName(std::move(alias_target))) {}

}  // namespace net
