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

#include "src/connectivity/network/mdns/service/agents/service_instance_resolver.h"

#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>

#include "src/connectivity/network/mdns/service/common/mdns_fidl_util.h"
#include "src/connectivity/network/mdns/service/common/mdns_names.h"
#include "src/connectivity/network/mdns/service/common/type_converters.h"

namespace mdns {
namespace {
constexpr zx::duration kAdditionalInterval = zx::sec(1);
constexpr uint32_t kAdditionalIntervalMultiplier = 2;
constexpr uint32_t kAdditionalMaxQueries = 3;
}  // namespace

ServiceInstanceResolver::ServiceInstanceResolver(MdnsAgent::Owner* owner,
                                                 const std::string& service,
                                                 const std::string& instance, zx::time timeout,
                                                 Media media, IpVersions ip_versions,
                                                 bool include_local, bool include_local_proxies,
                                                 Mdns::ResolveServiceInstanceCallback callback)
    : MdnsAgent(owner),
      service_(service),
      instance_name_(instance),
      timeout_(timeout),
      media_(media),
      ip_versions_(ip_versions),
      include_local_(include_local),
      include_local_proxies_(include_local_proxies),
      callback_(std::move(callback)),
      aaaa_queried_(false) {
  FX_DCHECK(callback_);
}

ServiceInstanceResolver::~ServiceInstanceResolver() {}

void ServiceInstanceResolver::Quit() {
  if (callback_) {
    callback_(std::move(instance_));
    callback_ = nullptr;
  }

  MdnsAgent::Quit();
}

void ServiceInstanceResolver::EndOfMessage() {
  if (!callback_) {
    // This can happen when a redundant response is received after the block below runs and before
    // the posted task runs, e.g. when two NICs are connected to the same LAN.
    return;
  }

  // if srv was received but has no aaaa record, send aaaa query.
  // Since nsec is not supported, the following check is intentional as
  // ServiceInstanceResolver supports only v6 addresses.
  if (!aaaa_queried_ && instance_.has_service() && !instance_.has_ipv6_endpoint()) {
    Query(DnsType::kAaaa, target_full_name_, media_, ip_versions_, now(), kAdditionalInterval,
          kAdditionalIntervalMultiplier, kAdditionalMaxQueries, true);
    aaaa_queried_ = true;
    return;
  }

  if (port_.is_valid() && instance_.has_ipv6_endpoint()) {
    callback_(std::move(instance_));
    callback_ = nullptr;
    PostTaskForTime([this]() { RemoveSelf(); }, now());
  }
}

void ServiceInstanceResolver::Start(const std::string& service_instance) {
  MdnsAgent::Start(service_instance);
  service_instance_ = MdnsNames::InstanceFullName(instance_name_, service_);
  // Increase the chance of coalescing the queries together in one message.
  auto ts = now();
  Query(DnsType::kSrv, service_instance_, media_, ip_versions_, ts, kAdditionalInterval,
        kAdditionalIntervalMultiplier, kAdditionalMaxQueries, true);
  Query(DnsType::kTxt, service_instance_, media_, ip_versions_, ts, kAdditionalInterval,
        kAdditionalIntervalMultiplier, kAdditionalMaxQueries, true);

  PostTaskForTime(
      [this]() {
        if (callback_) {
          callback_(std::move(instance_));
          callback_ = nullptr;
          RemoveSelf();
        }
      },
      timeout_);
}

void ServiceInstanceResolver::ReceiveResource(const DnsResource& resource,
                                              MdnsResourceSection section,
                                              ReplyAddress sender_address) {
  if (!sender_address.Matches(media_) || !sender_address.Matches(ip_versions_)) {
    return;
  }

  switch (resource.type_) {
    case DnsType::kSrv:
      if (resource.name_.dotted_string_ == service_instance_) {
        instance_.set_service(service_);
        instance_.set_instance(instance_name_);
        instance_.set_srv_priority(resource.srv_.priority_);
        instance_.set_srv_weight(resource.srv_.weight_);
        port_ = resource.srv_.port_;
        target_full_name_ = resource.srv_.target_.dotted_string_;
        instance_.set_target(MdnsNames::HostNameFromFullName(target_full_name_));
      }
      break;
    case DnsType::kA:
      if (resource.name_.dotted_string_ == target_full_name_) {
        auto address = MdnsFidlUtil::CreateSocketAddressV4(
            inet::SocketAddress(resource.a_.address_.address_, port_));
        instance_.set_ipv4_endpoint(address);
        if (!instance_.has_addresses()) {
          instance_.set_addresses(std::vector<fuchsia::net::SocketAddress>());
        }

        instance_.mutable_addresses()->push_back(
            fuchsia::net::SocketAddress::WithIpv4(std::move(address)));
      }
      break;
    case DnsType::kAaaa:
      if (resource.name_.dotted_string_ == target_full_name_) {
        // Add scope_id only to link local addresses.
        uint32_t scope_id = 0;
        if (resource.aaaa_.address_.address_.is_link_local()) {
          scope_id = sender_address.interface_id();
        }
        auto address = MdnsFidlUtil::CreateSocketAddressV6(
            inet::SocketAddress(resource.aaaa_.address_.address_, port_, scope_id));
        instance_.set_ipv6_endpoint(address);
        if (!instance_.has_addresses()) {
          instance_.set_addresses(std::vector<fuchsia::net::SocketAddress>());
        }

        instance_.mutable_addresses()->push_back(
            fuchsia::net::SocketAddress::WithIpv6(std::move(address)));
      }
      break;
    case DnsType::kTxt:
      if (resource.name_.dotted_string_ == target_full_name_) {
        instance_.set_text(fidl::To<std::vector<std::string>>(resource.txt_.strings_));
        instance_.set_text_strings(fidl::Clone(resource.txt_.strings_));
      }
      break;
    default:
      break;
  }
}

void ServiceInstanceResolver::OnAddLocalServiceInstance(const Mdns::ServiceInstance& instance,
                                                        bool from_proxy) {
  if (!callback_) {
    return;
  }

  if (from_proxy ? !include_local_proxies_ : !include_local_) {
    return;
  }

  if (instance.service_name_ != service_ || instance.instance_name_ != instance_name_) {
    return;
  }

  callback_(fidl::To<fuchsia::net::mdns::ServiceInstance>(instance));
  callback_ = nullptr;
  PostTaskForTime([this]() { RemoveSelf(); }, now());
}

}  // namespace mdns
