// Copyright 2017 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/instance_requestor.h"

#include <lib/zx/time.h>

#include "src/connectivity/network/mdns/service/mdns_names.h"
#include "src/lib/syslog/cpp/logger.h"

namespace mdns {
namespace {

// static
static constexpr zx::duration kMaxQueryInterval = zx::sec(60 * 60);

}  // namespace

InstanceRequestor::InstanceRequestor(MdnsAgent::Host* host, const std::string& service_name)
    : MdnsAgent(host),
      service_name_(service_name),
      service_full_name_(MdnsNames::LocalServiceFullName(service_name)),
      question_(std::make_shared<DnsQuestion>(service_full_name_, DnsType::kPtr)) {}

InstanceRequestor::~InstanceRequestor() {}

void InstanceRequestor::AddSubscriber(Mdns::Subscriber* subscriber) {
  subscribers_.insert(subscriber);
  if (started()) {
    ReportAllDiscoveries(subscriber);
  }
}

void InstanceRequestor::RemoveSubscriber(Mdns::Subscriber* subscriber) {
  subscribers_.erase(subscriber);
  if (subscribers_.empty()) {
    Quit();
  }
}

void InstanceRequestor::Start(const std::string& host_full_name, const MdnsAddresses& addresses) {
  MdnsAgent::Start(host_full_name, addresses);
  SendQuery();
}

void InstanceRequestor::ReceiveResource(const DnsResource& resource, MdnsResourceSection section) {
  switch (resource.type_) {
    case DnsType::kPtr:
      if (resource.name_.dotted_string_ == service_full_name_) {
        ReceivePtrResource(resource, section);
      }
      break;
    case DnsType::kSrv: {
      auto iter = instance_infos_by_full_name_.find(resource.name_.dotted_string_);
      if (iter != instance_infos_by_full_name_.end()) {
        ReceiveSrvResource(resource, section, &iter->second);
      }
    } break;
    case DnsType::kTxt: {
      auto iter = instance_infos_by_full_name_.find(resource.name_.dotted_string_);
      if (iter != instance_infos_by_full_name_.end()) {
        ReceiveTxtResource(resource, section, &iter->second);
      }
    } break;
    case DnsType::kA: {
      auto iter = target_infos_by_full_name_.find(resource.name_.dotted_string_);
      if (iter != target_infos_by_full_name_.end()) {
        ReceiveAResource(resource, section, &iter->second);
      }
    } break;
    case DnsType::kAaaa: {
      auto iter = target_infos_by_full_name_.find(resource.name_.dotted_string_);
      if (iter != target_infos_by_full_name_.end()) {
        ReceiveAaaaResource(resource, section, &iter->second);
      }
    } break;
    default:
      break;
  }
}

void InstanceRequestor::EndOfMessage() {
  // Report updates.
  for (auto& pair : instance_infos_by_full_name_) {
    InstanceInfo& instance_info = pair.second;

    if (instance_info.target_.empty()) {
      // We haven't yet seen an SRV record for this instance.
      continue;
    }

    auto iter = target_infos_by_full_name_.find(instance_info.target_);
    FX_DCHECK(iter != target_infos_by_full_name_.end());
    TargetInfo& target_info = iter->second;

    // Keep this target info around.
    target_info.keep_ = true;

    if (!instance_info.dirty_ && !target_info.dirty_) {
      // Both the instance info and target info are clean.
      continue;
    }

    if (!target_info.v4_address_ && !target_info.v6_address_) {
      // No addresses yet.
      continue;
    }

    // Something has changed.
    if (instance_info.new_) {
      instance_info.new_ = false;
      for (auto subscriber : subscribers_) {
        subscriber->InstanceDiscovered(
            service_name_, instance_info.instance_name_,
            inet::SocketAddress(target_info.v4_address_, instance_info.port_),
            inet::SocketAddress(target_info.v6_address_, instance_info.port_), instance_info.text_,
            instance_info.srv_priority_, instance_info.srv_weight_);
      }
    } else {
      for (auto subscriber : subscribers_) {
        subscriber->InstanceChanged(
            service_name_, instance_info.instance_name_,
            inet::SocketAddress(target_info.v4_address_, instance_info.port_),
            inet::SocketAddress(target_info.v6_address_, instance_info.port_), instance_info.text_,
            instance_info.srv_priority_, instance_info.srv_weight_);
      }
    }

    instance_info.dirty_ = false;
  }

  // Clean up |target_infos_by_full_name_|.
  for (auto iter = target_infos_by_full_name_.begin(); iter != target_infos_by_full_name_.end();) {
    if (iter->second.keep_) {
      iter->second.dirty_ = false;
      iter->second.keep_ = false;
      ++iter;
    } else {
      // No instances reference this target. Get rid of it.
      iter = target_infos_by_full_name_.erase(iter);
    }
  }
}

void InstanceRequestor::ReportAllDiscoveries(Mdns::Subscriber* subscriber) {
  bool updates_happened = false;

  for (auto& pair : instance_infos_by_full_name_) {
    InstanceInfo& instance_info = pair.second;

    if (instance_info.target_.empty()) {
      // We haven't yet seen an SRV record for this instance.
      continue;
    }

    auto iter = target_infos_by_full_name_.find(instance_info.target_);
    FX_DCHECK(iter != target_infos_by_full_name_.end());
    TargetInfo& target_info = iter->second;

    if (!target_info.v4_address_ && !target_info.v6_address_) {
      // No addresses yet.
      continue;
    }

    updates_happened = true;
    subscriber->InstanceDiscovered(
        service_name_, instance_info.instance_name_,
        inet::SocketAddress(target_info.v4_address_, instance_info.port_),
        inet::SocketAddress(target_info.v6_address_, instance_info.port_), instance_info.text_,
        instance_info.srv_priority_, instance_info.srv_weight_);
  }
}

void InstanceRequestor::SendQuery() {
  SendQuestion(question_);
  for (auto& subscriber : subscribers_) {
    subscriber->Query(question_->type_);
  }

  if (query_delay_ == zx::sec(0)) {
    query_delay_ = zx::sec(1);
  } else {
    query_delay_ = query_delay_ * 2;
    if (query_delay_ > kMaxQueryInterval) {
      query_delay_ = kMaxQueryInterval;
    }
  }

  PostTaskForTime([this]() { SendQuery(); }, now() + query_delay_);
}

void InstanceRequestor::ReceivePtrResource(const DnsResource& resource,
                                           MdnsResourceSection section) {
  const std::string& instance_full_name = resource.ptr_.pointer_domain_name_.dotted_string_;

  std::string instance_name;
  if (!MdnsNames::ExtractInstanceName(instance_full_name, service_name_, &instance_name)) {
    return;
  }

  if (resource.time_to_live_ == 0) {
    RemoveInstance(instance_full_name);
    return;
  }

  if (instance_infos_by_full_name_.find(instance_full_name) == instance_infos_by_full_name_.end()) {
    auto pair = instance_infos_by_full_name_.emplace(instance_full_name, InstanceInfo{});
    FX_DCHECK(pair.second);
    pair.first->second.instance_name_ = instance_name;
  }

  Renew(resource);
}

void InstanceRequestor::ReceiveSrvResource(const DnsResource& resource, MdnsResourceSection section,
                                           InstanceInfo* instance_info) {
  if (resource.time_to_live_ == 0) {
    RemoveInstance(resource.name_.dotted_string_);
    return;
  }

  if (instance_info->target_ != resource.srv_.target_.dotted_string_) {
    instance_info->target_ = resource.srv_.target_.dotted_string_;
    instance_info->dirty_ = true;

    if (target_infos_by_full_name_.find(instance_info->target_) ==
        target_infos_by_full_name_.end()) {
      target_infos_by_full_name_.emplace(instance_info->target_, TargetInfo{});
    }
  }

  if (instance_info->srv_priority_ != resource.srv_.priority_) {
    instance_info->srv_priority_ = resource.srv_.priority_;
    instance_info->dirty_ = true;
  }

  if (instance_info->srv_weight_ != resource.srv_.weight_) {
    instance_info->srv_weight_ = resource.srv_.weight_;
    instance_info->dirty_ = true;
  }

  if (instance_info->port_ != resource.srv_.port_) {
    instance_info->port_ = resource.srv_.port_;
    instance_info->dirty_ = true;
  }

  Renew(resource);
}

void InstanceRequestor::ReceiveTxtResource(const DnsResource& resource, MdnsResourceSection section,
                                           InstanceInfo* instance_info) {
  if (resource.time_to_live_ == 0) {
    if (!instance_info->text_.empty()) {
      instance_info->text_.clear();
      instance_info->dirty_ = true;
    }

    return;
  }

  if (instance_info->text_.size() != resource.txt_.strings_.size()) {
    instance_info->text_.resize(resource.txt_.strings_.size());
    instance_info->dirty_ = true;
  }

  for (size_t i = 0; i < instance_info->text_.size(); ++i) {
    if (instance_info->text_[i] != resource.txt_.strings_[i]) {
      instance_info->text_[i] = resource.txt_.strings_[i];
      instance_info->dirty_ = true;
    }
  }

  Renew(resource);
}

void InstanceRequestor::ReceiveAResource(const DnsResource& resource, MdnsResourceSection section,
                                         TargetInfo* target_info) {
  if (resource.time_to_live_ == 0) {
    if (target_info->v4_address_) {
      target_info->v4_address_ = inet::IpAddress::kInvalid;
      target_info->dirty_ = true;
    }

    return;
  }

  if (target_info->v4_address_ != resource.a_.address_.address_) {
    target_info->v4_address_ = resource.a_.address_.address_;
    target_info->dirty_ = true;
  }

  Renew(resource);
}

void InstanceRequestor::ReceiveAaaaResource(const DnsResource& resource,
                                            MdnsResourceSection section, TargetInfo* target_info) {
  if (resource.time_to_live_ == 0) {
    if (target_info->v6_address_) {
      target_info->v6_address_ = inet::IpAddress::kInvalid;
      target_info->dirty_ = true;
    }

    return;
  }

  if (target_info->v6_address_ != resource.aaaa_.address_.address_) {
    target_info->v6_address_ = resource.aaaa_.address_.address_;
    target_info->dirty_ = true;
  }

  Renew(resource);
}

void InstanceRequestor::RemoveInstance(const std::string& instance_full_name) {
  auto iter = instance_infos_by_full_name_.find(instance_full_name);
  if (iter != instance_infos_by_full_name_.end()) {
    for (auto subscriber : subscribers_) {
      subscriber->InstanceLost(service_name_, iter->second.instance_name_);
    }

    instance_infos_by_full_name_.erase(iter);
  }
}

}  // namespace mdns
