// Copyright 2020 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/https_record_rdata.h"

#include <stdint.h>

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

#include "base/big_endian.h"
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/dcheck_is_on.h"
#include "base/immediate_crash.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h"
#include "net/base/ip_address.h"
#include "net/dns/dns_names_util.h"
#include "net/dns/public/dns_protocol.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace net {

namespace {

bool ReadNextServiceParam(absl::optional<uint16_t> last_key,
                          base::BigEndianReader& reader,
                          uint16_t* out_param_key,
                          base::StringPiece* out_param_value) {
  DCHECK(out_param_key);
  DCHECK(out_param_value);

  uint16_t key;
  if (!reader.ReadU16(&key))
    return false;
  if (last_key.has_value() && last_key.value() >= key)
    return false;

  base::StringPiece value;
  if (!reader.ReadU16LengthPrefixed(&value))
    return false;

  *out_param_key = key;
  *out_param_value = value;
  return true;
}

bool ParseMandatoryKeys(base::StringPiece param_value,
                        std::set<uint16_t>* out_parsed) {
  DCHECK(out_parsed);

  auto reader = base::BigEndianReader::FromStringPiece(param_value);

  std::set<uint16_t> mandatory_keys;
  // Do/while to require at least one key.
  do {
    uint16_t key;
    if (!reader.ReadU16(&key))
      return false;

    // Mandatory key itself is disallowed from its list.
    if (key == dns_protocol::kHttpsServiceParamKeyMandatory)
      return false;
    // Keys required to be listed in ascending order.
    if (!mandatory_keys.empty() && key <= *mandatory_keys.rbegin())
      return false;

    CHECK(mandatory_keys.insert(key).second);
  } while (reader.remaining() > 0);

  *out_parsed = std::move(mandatory_keys);
  return true;
}

bool ParseAlpnIds(base::StringPiece param_value,
                  std::vector<std::string>* out_parsed) {
  DCHECK(out_parsed);

  auto reader = base::BigEndianReader::FromStringPiece(param_value);

  std::vector<std::string> alpn_ids;
  // Do/while to require at least one ID.
  do {
    base::StringPiece alpn_id;
    if (!reader.ReadU8LengthPrefixed(&alpn_id))
      return false;
    if (alpn_id.size() < 1)
      return false;
    DCHECK_LE(alpn_id.size(), 255u);

    alpn_ids.emplace_back(alpn_id.data(), alpn_id.size());
  } while (reader.remaining() > 0);

  *out_parsed = std::move(alpn_ids);
  return true;
}

template <size_t ADDRESS_SIZE>
bool ParseIpAddresses(base::StringPiece param_value,
                      std::vector<IPAddress>* out_addresses) {
  DCHECK(out_addresses);

  auto reader = base::BigEndianReader::FromStringPiece(param_value);

  std::vector<IPAddress> addresses;
  uint8_t addr_bytes[ADDRESS_SIZE];
  do {
    if (!reader.ReadBytes(addr_bytes, ADDRESS_SIZE))
      return false;
    addresses.emplace_back(addr_bytes);
    DCHECK(addresses.back().IsValid());
  } while (reader.remaining() > 0);

  *out_addresses = std::move(addresses);
  return true;
}

}  // namespace

// static
std::unique_ptr<HttpsRecordRdata> HttpsRecordRdata::Parse(
    base::StringPiece data) {
  if (!HasValidSize(data, kType))
    return nullptr;

  auto reader = base::BigEndianReader::FromStringPiece(data);
  uint16_t priority;
  CHECK(reader.ReadU16(&priority));

  if (priority == 0) {
    return AliasFormHttpsRecordRdata::Parse(data);
  }
  return ServiceFormHttpsRecordRdata::Parse(data);
}

HttpsRecordRdata::~HttpsRecordRdata() = default;

bool HttpsRecordRdata::IsEqual(const RecordRdata* other) const {
  DCHECK(other);

  if (other->Type() != kType)
    return false;

  const HttpsRecordRdata* https = static_cast<const HttpsRecordRdata*>(other);
  return IsEqual(https);
}

uint16_t HttpsRecordRdata::Type() const {
  return kType;
}

AliasFormHttpsRecordRdata* HttpsRecordRdata::AsAliasForm() {
  CHECK(IsAlias());
  return static_cast<AliasFormHttpsRecordRdata*>(this);
}

const AliasFormHttpsRecordRdata* HttpsRecordRdata::AsAliasForm() const {
  return const_cast<HttpsRecordRdata*>(this)->AsAliasForm();
}

ServiceFormHttpsRecordRdata* HttpsRecordRdata::AsServiceForm() {
  CHECK(!IsAlias());
  return static_cast<ServiceFormHttpsRecordRdata*>(this);
}

const ServiceFormHttpsRecordRdata* HttpsRecordRdata::AsServiceForm() const {
  return const_cast<HttpsRecordRdata*>(this)->AsServiceForm();
}

AliasFormHttpsRecordRdata::AliasFormHttpsRecordRdata(std::string alias_name)
    : alias_name_(std::move(alias_name)) {}

// static
std::unique_ptr<AliasFormHttpsRecordRdata> AliasFormHttpsRecordRdata::Parse(
    base::StringPiece data) {
  auto reader = base::BigEndianReader::FromStringPiece(data);

  uint16_t priority;
  if (!reader.ReadU16(&priority))
    return nullptr;
  if (priority != 0)
    return nullptr;

  absl::optional<std::string> alias_name =
      dns_names_util::NetworkToDottedName(reader, true /* require_complete */);
  if (!alias_name.has_value())
    return nullptr;

  // Ignore any params.
  absl::optional<uint16_t> last_param_key;
  while (reader.remaining() > 0) {
    uint16_t param_key;
    base::StringPiece param_value;
    if (!ReadNextServiceParam(last_param_key, reader, &param_key, &param_value))
      return nullptr;
    last_param_key = param_key;
  }

  return std::make_unique<AliasFormHttpsRecordRdata>(
      std::move(alias_name).value());
}

bool AliasFormHttpsRecordRdata::IsEqual(const HttpsRecordRdata* other) const {
  DCHECK(other);

  if (!other->IsAlias())
    return false;

  const AliasFormHttpsRecordRdata* alias = other->AsAliasForm();
  return alias_name_ == alias->alias_name_;
}

bool AliasFormHttpsRecordRdata::IsAlias() const {
  return true;
}

// static
constexpr uint16_t ServiceFormHttpsRecordRdata::kSupportedKeys[];

ServiceFormHttpsRecordRdata::ServiceFormHttpsRecordRdata(
    HttpsRecordPriority priority,
    std::string service_name,
    std::set<uint16_t> mandatory_keys,
    std::vector<std::string> alpn_ids,
    bool default_alpn,
    absl::optional<uint16_t> port,
    std::vector<IPAddress> ipv4_hint,
    std::string ech_config,
    std::vector<IPAddress> ipv6_hint,
    std::map<uint16_t, std::string> unparsed_params)
    : priority_(priority),
      service_name_(std::move(service_name)),
      mandatory_keys_(std::move(mandatory_keys)),
      alpn_ids_(std::move(alpn_ids)),
      default_alpn_(default_alpn),
      port_(port),
      ipv4_hint_(std::move(ipv4_hint)),
      ech_config_(std::move(ech_config)),
      ipv6_hint_(std::move(ipv6_hint)),
      unparsed_params_(std::move(unparsed_params)) {
  DCHECK_NE(priority_, 0);
  DCHECK(mandatory_keys_.find(dns_protocol::kHttpsServiceParamKeyMandatory) ==
         mandatory_keys_.end());

#if DCHECK_IS_ON()
  for (const IPAddress& address : ipv4_hint_) {
    DCHECK(address.IsIPv4());
  }
  for (const IPAddress& address : ipv6_hint_) {
    DCHECK(address.IsIPv6());
  }
  for (const auto& unparsed_param : unparsed_params_) {
    DCHECK(!IsSupportedKey(unparsed_param.first));
  }
#endif  // DCHECK_IS_ON()
}

ServiceFormHttpsRecordRdata::~ServiceFormHttpsRecordRdata() = default;

bool ServiceFormHttpsRecordRdata::IsEqual(const HttpsRecordRdata* other) const {
  DCHECK(other);

  if (other->IsAlias())
    return false;

  const ServiceFormHttpsRecordRdata* service = other->AsServiceForm();
  return priority_ == service->priority_ &&
         service_name_ == service->service_name_ &&
         mandatory_keys_ == service->mandatory_keys_ &&
         alpn_ids_ == service->alpn_ids_ &&
         default_alpn_ == service->default_alpn_ && port_ == service->port_ &&
         ipv4_hint_ == service->ipv4_hint_ &&
         ech_config_ == service->ech_config_ &&
         ipv6_hint_ == service->ipv6_hint_;
}

bool ServiceFormHttpsRecordRdata::IsAlias() const {
  return false;
}

// static
std::unique_ptr<ServiceFormHttpsRecordRdata> ServiceFormHttpsRecordRdata::Parse(
    base::StringPiece data) {
  auto reader = base::BigEndianReader::FromStringPiece(data);

  uint16_t priority;
  if (!reader.ReadU16(&priority))
    return nullptr;
  if (priority == 0)
    return nullptr;

  absl::optional<std::string> service_name =
      dns_names_util::NetworkToDottedName(reader, true /* require_complete */);
  if (!service_name.has_value())
    return nullptr;

  if (reader.remaining() == 0) {
    return std::make_unique<ServiceFormHttpsRecordRdata>(
        HttpsRecordPriority{priority}, std::move(service_name).value(),
        std::set<uint16_t>() /* mandatory_keys */,
        std::vector<std::string>() /* alpn_ids */, true /* default_alpn */,
        absl::nullopt /* port */, std::vector<IPAddress>() /* ipv4_hint */,
        std::string() /* ech_config */,
        std::vector<IPAddress>() /* ipv6_hint */,
        std::map<uint16_t, std::string>() /* unparsed_params */);
  }

  uint16_t param_key = 0;
  base::StringPiece param_value;
  if (!ReadNextServiceParam(absl::nullopt /* last_key */, reader, &param_key,
                            &param_value))
    return nullptr;

  // Assume keys less than Mandatory are not possible.
  DCHECK_GE(param_key, dns_protocol::kHttpsServiceParamKeyMandatory);

  std::set<uint16_t> mandatory_keys;
  if (param_key == dns_protocol::kHttpsServiceParamKeyMandatory) {
    DCHECK(IsSupportedKey(param_key));
    if (!ParseMandatoryKeys(param_value, &mandatory_keys))
      return nullptr;
    if (reader.remaining() > 0 &&
        !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
      return nullptr;
    }
  }

  std::vector<std::string> alpn_ids;
  if (param_key == dns_protocol::kHttpsServiceParamKeyAlpn) {
    DCHECK(IsSupportedKey(param_key));
    if (!ParseAlpnIds(param_value, &alpn_ids))
      return nullptr;
    if (reader.remaining() > 0 &&
        !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
      return nullptr;
    }
  }

  bool default_alpn = true;
  if (param_key == dns_protocol::kHttpsServiceParamKeyNoDefaultAlpn) {
    DCHECK(IsSupportedKey(param_key));
    if (!param_value.empty())
      return nullptr;
    default_alpn = false;
    if (reader.remaining() > 0 &&
        !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
      return nullptr;
    }
  }

  absl::optional<uint16_t> port;
  if (param_key == dns_protocol::kHttpsServiceParamKeyPort) {
    DCHECK(IsSupportedKey(param_key));
    if (param_value.size() != 2)
      return nullptr;
    uint16_t port_val;
    base::ReadBigEndian(reinterpret_cast<const uint8_t*>(param_value.data()),
                        &port_val);
    port = port_val;
    if (reader.remaining() > 0 &&
        !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
      return nullptr;
    }
  }

  std::vector<IPAddress> ipv4_hint;
  if (param_key == dns_protocol::kHttpsServiceParamKeyIpv4Hint) {
    DCHECK(IsSupportedKey(param_key));
    if (!ParseIpAddresses<IPAddress::kIPv4AddressSize>(param_value, &ipv4_hint))
      return nullptr;
    if (reader.remaining() > 0 &&
        !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
      return nullptr;
    }
  }

  std::string ech_config;
  if (param_key == dns_protocol::kHttpsServiceParamKeyEchConfig) {
    DCHECK(IsSupportedKey(param_key));
    ech_config = std::string(param_value.data(), param_value.size());
    if (reader.remaining() > 0 &&
        !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
      return nullptr;
    }
  }

  std::vector<IPAddress> ipv6_hint;
  if (param_key == dns_protocol::kHttpsServiceParamKeyIpv6Hint) {
    DCHECK(IsSupportedKey(param_key));
    if (!ParseIpAddresses<IPAddress::kIPv6AddressSize>(param_value, &ipv6_hint))
      return nullptr;
    if (reader.remaining() > 0 &&
        !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
      return nullptr;
    }
  }

  // Note that if parsing has already reached the end of the rdata, `param_key`
  // is still set for whatever param was read last.
  std::map<uint16_t, std::string> unparsed_params;
  if (param_key > dns_protocol::kHttpsServiceParamKeyIpv6Hint) {
    for (;;) {
      DCHECK(!IsSupportedKey(param_key));
      CHECK(unparsed_params
                .emplace(param_key, static_cast<std::string>(param_value))
                .second);
      if (reader.remaining() == 0)
        break;
      if (!ReadNextServiceParam(param_key, reader, &param_key, &param_value))
        return nullptr;
    }
  }

  return std::make_unique<ServiceFormHttpsRecordRdata>(
      HttpsRecordPriority{priority}, std::move(service_name).value(),
      std::move(mandatory_keys), std::move(alpn_ids), default_alpn, port,
      std::move(ipv4_hint), std::move(ech_config), std::move(ipv6_hint),
      std::move(unparsed_params));
}

bool ServiceFormHttpsRecordRdata::IsCompatible() const {
  std::set<uint16_t> supported_keys(std::begin(kSupportedKeys),
                                    std::end(kSupportedKeys));

  for (uint16_t mandatory_key : mandatory_keys_) {
    DCHECK_NE(mandatory_key, dns_protocol::kHttpsServiceParamKeyMandatory);

    if (supported_keys.find(mandatory_key) == supported_keys.end())
      return false;
  }

#if DCHECK_IS_ON()
  for (const auto& unparsed_param : unparsed_params_) {
    DCHECK(mandatory_keys_.find(unparsed_param.first) == mandatory_keys_.end());
  }
#endif  // DCHECK_IS_ON()

  return true;
}

// static
bool ServiceFormHttpsRecordRdata::IsSupportedKey(uint16_t key) {
#if DCHECK_IS_ON()
  return base::Contains(kSupportedKeys, key);
#else
  // Only intended for DCHECKs.
  base::ImmediateCrash();
#endif  // DCHECK_IS_ON()
}

}  // namespace net
