// Copyright 2019 The Chromium 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 "discovery/mdns/mdns_responder.h"

#include <string>
#include <utility>

#include "discovery/common/config.h"
#include "discovery/mdns/mdns_probe_manager.h"
#include "discovery/mdns/mdns_publisher.h"
#include "discovery/mdns/mdns_querier.h"
#include "discovery/mdns/mdns_random.h"
#include "discovery/mdns/mdns_receiver.h"
#include "discovery/mdns/mdns_sender.h"
#include "platform/api/task_runner.h"

namespace openscreen {
namespace discovery {
namespace {

const std::array<std::string, 3> kServiceEnumerationDomainLabels{
    "_services", "_dns-sd", "_udp"};

enum AddResult { kNonePresent = 0, kAdded, kAlreadyKnown };

std::chrono::seconds GetTtlForNsecTargetingType(DnsType type) {
  // NOTE: A 'default' switch statement has intentionally been avoided below to
  // enforce that new DnsTypes added must be added below through a compile-time
  // check.
  switch (type) {
    case DnsType::kA:
      return kARecordTtl;
    case DnsType::kAAAA:
      return kAAAARecordTtl;
    case DnsType::kPTR:
      return kPtrRecordTtl;
    case DnsType::kSRV:
      return kSrvRecordTtl;
    case DnsType::kTXT:
      return kTXTRecordTtl;
    case DnsType::kANY:
      // If no records are present, re-querying should happen at the minimum
      // of any record that might be retrieved at that time.
      return kSrvRecordTtl;
    case DnsType::kNSEC:
    case DnsType::kOPT:
      // Neither of these types should ever be hit. We should never be creating
      // an NSEC record for type NSEC, and OPT record querying is not supported,
      // so creating NSEC records for type OPT is not valid.
      break;
  }

  OSP_NOTREACHED();
}

MdnsRecord CreateNsecRecord(DomainName target_name,
                            DnsType target_type,
                            DnsClass target_class) {
  auto rdata = NsecRecordRdata(target_name, target_type);
  std::chrono::seconds ttl = GetTtlForNsecTargetingType(target_type);
  return MdnsRecord(std::move(target_name), DnsType::kNSEC, target_class,
                    RecordType::kUnique, ttl, std::move(rdata));
}

inline bool IsValidAdditionalRecordType(DnsType type) {
  return type == DnsType::kSRV || type == DnsType::kTXT ||
         type == DnsType::kA || type == DnsType::kAAAA;
}

AddResult AddRecords(std::function<void(MdnsRecord record)> add_func,
                     MdnsResponder::RecordHandler* record_handler,
                     const DomainName& domain,
                     const std::vector<MdnsRecord>& known_answers,
                     DnsType type,
                     DnsClass clazz,
                     bool add_negative_on_unknown) {
  auto records = record_handler->GetRecords(domain, type, clazz);
  if (records.empty()) {
    if (add_negative_on_unknown) {
      // TODO(rwkeane): Aggregate all NSEC records together into a single NSEC
      // record to reduce traffic.
      add_func(CreateNsecRecord(domain, type, clazz));
    }
    return AddResult::kNonePresent;
  } else {
    bool added_any_records = false;
    for (auto it = records.begin(); it != records.end(); it++) {
      if (std::find(known_answers.begin(), known_answers.end(), *it) ==
          known_answers.end()) {
        added_any_records = true;
        add_func(std::move(*it));
      }
    }
    return added_any_records ? AddResult::kAdded : AddResult::kAlreadyKnown;
  }
}

inline AddResult AddAdditionalRecords(
    MdnsMessage* message,
    MdnsResponder::RecordHandler* record_handler,
    const DomainName& domain,
    const std::vector<MdnsRecord>& known_answers,
    DnsType type,
    DnsClass clazz,
    bool add_negative_on_unknown) {
  OSP_DCHECK(IsValidAdditionalRecordType(type));

  auto add_func = [message](MdnsRecord record) {
    message->AddAdditionalRecord(std::move(record));
  };
  return AddRecords(std::move(add_func), record_handler, domain, known_answers,
                    type, clazz, add_negative_on_unknown);
}

inline AddResult AddResponseRecords(
    MdnsMessage* message,
    MdnsResponder::RecordHandler* record_handler,
    const DomainName& domain,
    const std::vector<MdnsRecord>& known_answers,
    DnsType type,
    DnsClass clazz,
    bool add_negative_on_unknown) {
  auto add_func = [message](MdnsRecord record) {
    message->AddAnswer(std::move(record));
  };
  return AddRecords(std::move(add_func), record_handler, domain, known_answers,
                    type, clazz, add_negative_on_unknown);
}

void ApplyQueryResults(MdnsMessage* message,
                       MdnsResponder::RecordHandler* record_handler,
                       const DomainName& domain,
                       const std::vector<MdnsRecord>& known_answers,
                       DnsType type,
                       DnsClass clazz,
                       bool is_exclusive_owner) {
  OSP_DCHECK(type != DnsType::kNSEC);

  // All records matching the provided query which have been published by this
  // host should be added to the response message per RFC 6762 section 6. If
  // this host is the exclusive owner of the queried domain name, then a
  // negative response NSEC record should be added in the case where the queried
  // record does not exist, per RFC 6762 section 6.1.
  if (AddResponseRecords(message, record_handler, domain, known_answers, type,
                         clazz, is_exclusive_owner) != AddResult::kAdded) {
    return;
  }

  // Per RFC 6763 section 12.1, when querying for a PTR record, all SRV records
  // and TXT records named in the PTR record's rdata should be added to the
  // messages additional records, as well as the address records of types A and
  // AAAA associated with the added SRV records. Per RFC 6762 section 6.1,
  // records with names matching those of reverse address mappings for PTR
  // records may be added as negative response NSEC records if they do not
  // exist.
  if (type == DnsType::kPTR) {
    // Add all SRV and TXT records to the additional records section.
    for (const MdnsRecord& record : message->answers()) {
      OSP_DCHECK(record.dns_type() == DnsType::kPTR);

      const DomainName& target =
          absl::get<PtrRecordRdata>(record.rdata()).ptr_domain();
      AddAdditionalRecords(message, record_handler, target, known_answers,
                           DnsType::kSRV, clazz, true);
      AddAdditionalRecords(message, record_handler, target, known_answers,
                           DnsType::kTXT, clazz, true);
    }

    // Add A and AAAA records associated with an added SRV record to the
    // additional records section.
    const int max = message->additional_records().size();
    for (int i = 0; i < max; i++) {
      if (message->additional_records()[i].dns_type() != DnsType::kSRV) {
        continue;
      }

      {
        const MdnsRecord& srv_record = message->additional_records()[i];
        const DomainName& target =
            absl::get<SrvRecordRdata>(srv_record.rdata()).target();
        AddAdditionalRecords(message, record_handler, target, known_answers,
                             DnsType::kA, clazz, target == domain);
      }

      // Must re-calculate the |srv_record|, |target| refs in case a resize of
      // the additional_records() vector has invalidated them.
      {
        const MdnsRecord& srv_record = message->additional_records()[i];
        const DomainName& target =
            absl::get<SrvRecordRdata>(srv_record.rdata()).target();
        AddAdditionalRecords(message, record_handler, target, known_answers,
                             DnsType::kAAAA, clazz, target == domain);
      }
    }
  } else if (type == DnsType::kSRV) {
    // Per RFC 6763 section 12.2, when querying for an SRV record, all address
    // records of type A and AAAA should be added to the additional records
    // section. Per RFC 6762 section 6.1, if these records are not present and
    // their name and class match that which is being queried for, a negative
    // response NSEC record may be added to show their non-existence.
    for (const auto& srv_record : message->answers()) {
      OSP_DCHECK(srv_record.dns_type() == DnsType::kSRV);

      const DomainName& target =
          absl::get<SrvRecordRdata>(srv_record.rdata()).target();
      AddAdditionalRecords(message, record_handler, target, known_answers,
                           DnsType::kA, clazz, target == domain);
      AddAdditionalRecords(message, record_handler, target, known_answers,
                           DnsType::kAAAA, clazz, target == domain);
    }
  } else if (type == DnsType::kA) {
    // Per RFC 6762 section 6.2, when querying for an address record of type A
    // or AAAA, the record of the opposite type should be added to the
    // additional records section if present. Else, a negative response NSEC
    // record should be added to show its non-existence.
    AddAdditionalRecords(message, record_handler, domain, known_answers,
                         DnsType::kAAAA, clazz, true);
  } else if (type == DnsType::kAAAA) {
    AddAdditionalRecords(message, record_handler, domain, known_answers,
                         DnsType::kA, clazz, true);
  }

  // The remaining supported records types are TXT, NSEC, and ANY. RFCs 6762 and
  // 6763 do not recommend sending any records in the additional records section
  // for queries of types TXT or ANY, and NSEC records are not supported for
  // queries.
}

// Determines if the provided query is a type enumeration query as described in
// RFC 6763 section 9.
bool IsServiceTypeEnumerationQuery(const MdnsQuestion& question) {
  if (question.dns_type() != DnsType::kPTR) {
    return false;
  }

  if (question.name().labels().size() <
      kServiceEnumerationDomainLabels.size()) {
    return false;
  }

  const auto question_it = question.name().labels().begin();
  return std::equal(question_it,
                    question_it + kServiceEnumerationDomainLabels.size(),
                    kServiceEnumerationDomainLabels.begin(),
                    kServiceEnumerationDomainLabels.end());
}

// Creates the expected response to a type enumeration query as described in RFC
// 6763 section 9.
void ApplyServiceTypeEnumerationResults(
    MdnsMessage* message,
    MdnsResponder::RecordHandler* record_handler,
    const DomainName& name,
    DnsClass clazz) {
  if (name.labels().size() < kServiceEnumerationDomainLabels.size()) {
    return;
  }

  std::vector<MdnsRecord::ConstRef> records =
      record_handler->GetPtrRecords(clazz);

  // skip "_services._dns-sd._udp." which was already checked for in above
  // method and just use the domain.
  const auto domain_it =
      name.labels().begin() + kServiceEnumerationDomainLabels.size();
  for (const MdnsRecord& record : records) {
    // Skip the 2 label service name in the PTR record's name.
    const auto record_it = record.name().labels().begin() + 2;
    if (std::equal(domain_it, name.labels().end(), record_it,
                   record.name().labels().end())) {
      message->AddAnswer(MdnsRecord(name, DnsType::kPTR, record.dns_class(),
                                    RecordType::kShared, record.ttl(),
                                    PtrRecordRdata(record.name())));
    }
  }
}

bool IsMultiPacketTruncatedQueryMessage(const MdnsMessage& message) {
  return message.is_truncated() || message.questions().empty();
}

}  // namespace

MdnsResponder::RecordHandler::~RecordHandler() = default;

MdnsResponder::TruncatedQuery::TruncatedQuery(MdnsResponder* responder,
                                              TaskRunner* task_runner,
                                              ClockNowFunctionPtr now_function,
                                              IPEndpoint src,
                                              const MdnsMessage& message,
                                              const Config& config)
    : max_allowed_messages_(config.maximum_truncated_messages_per_query),
      max_allowed_records_(config.maximum_known_answer_records_per_query),
      src_(std::move(src)),
      responder_(responder),
      questions_(message.questions()),
      known_answers_(message.answers()),
      alarm_(now_function, task_runner) {
  OSP_DCHECK(responder_);
  OSP_DCHECK_GT(max_allowed_messages_, 0);
  OSP_DCHECK_GT(max_allowed_records_, 0);

  RescheduleSend();
}

void MdnsResponder::TruncatedQuery::SetQuery(const MdnsMessage& message) {
  OSP_DCHECK(questions_.empty());
  questions_.insert(questions_.end(), message.questions().begin(),
                    message.questions().end());

  // |messages_received_so_far| does not need to be validated here because it is
  // checked as part of RescheduleSend().
  known_answers_.insert(known_answers_.end(), message.answers().begin(),
                        message.answers().end());
  messages_received_so_far++;

  RescheduleSend();
}

void MdnsResponder::TruncatedQuery::AddKnownAnswers(
    const std::vector<MdnsRecord>& records) {
  // |messages_received_so_far| does not need to be validated here because it is
  // checked as part of RescheduleSend().
  known_answers_.insert(known_answers_.end(), records.begin(), records.end());
  messages_received_so_far++;

  RescheduleSend();
}

void MdnsResponder::TruncatedQuery::RescheduleSend() {
  alarm_.Cancel();

  Clock::duration send_delay;
  if (messages_received_so_far >= max_allowed_messages_) {
    // Maximum number of truncated messages have already been received for this
    // query.
    send_delay = Clock::duration(0);
  } else if (known_answers_.size() >=
             static_cast<size_t>(max_allowed_records_)) {
    // Maximum number of known answer records have already been received for
    // this query.
    send_delay = Clock::duration(0);
  } else {
    // Reschedule to send after a random delay, per RFC 6762.
    send_delay = responder_->random_delay_->GetTruncatedQueryResponseDelay();
  }

  alarm_.ScheduleFromNow([this]() { SendResponse(); }, send_delay);
}

void MdnsResponder::TruncatedQuery::SendResponse() {
  alarm_.Cancel();

  if (questions_.empty()) {
    OSP_DVLOG << "Known answers received for unknown query, and non received "
                 "after delay. Dropping them...";
    return;
  }

  responder_->RespondToTruncatedQuery(this);
}

MdnsResponder::MdnsResponder(RecordHandler* record_handler,
                             MdnsProbeManager* ownership_handler,
                             MdnsSender* sender,
                             MdnsReceiver* receiver,
                             TaskRunner* task_runner,
                             ClockNowFunctionPtr now_function,
                             MdnsRandom* random_delay,
                             const Config& config)
    : record_handler_(record_handler),
      ownership_handler_(ownership_handler),
      sender_(sender),
      receiver_(receiver),
      task_runner_(task_runner),
      now_function_(now_function),
      random_delay_(random_delay),
      config_(config) {
  OSP_DCHECK(record_handler_);
  OSP_DCHECK(ownership_handler_);
  OSP_DCHECK(sender_);
  OSP_DCHECK(receiver_);
  OSP_DCHECK(task_runner_);
  OSP_DCHECK(random_delay_);
  OSP_DCHECK_GT(config_.maximum_truncated_messages_per_query, 0);
  OSP_DCHECK_GT(config_.maximum_concurrent_truncated_queries_per_interface, 0);

  auto func = [this](const MdnsMessage& message, const IPEndpoint& src) {
    OnMessageReceived(message, src);
  };
  receiver_->SetQueryCallback(std::move(func));
}

MdnsResponder::~MdnsResponder() {
  receiver_->SetQueryCallback(nullptr);
}

void MdnsResponder::OnMessageReceived(const MdnsMessage& message,
                                      const IPEndpoint& src) {
  OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
  OSP_DCHECK(message.type() == MessageType::Query);

  // Handle multi-packet known answer suppression.
  if (IsMultiPacketTruncatedQueryMessage(message)) {
    // If there have been an excessive number of known answers received already,
    // then skip them. This would most likely mean that:
    // - A host on the network is misbehaving.
    // - There is a malicious actor on the network.
    // In either of these cases, optimize for this host's resource usage.
    if (truncated_queries_.size() >
        static_cast<size_t>(
            config_.maximum_concurrent_truncated_queries_per_interface)) {
      OSP_DVLOG << "Too many truncated queries have been received. Treating "
                   "new multi-packet known answer message as normal query";
    } else {
      ProcessMultiPacketTruncatedMessage(message, src);
      return;
    }
  }

  // If the query is a probe query, it will be handled separately by the
  // MdnsProbeManager. Ignore it here.
  if (message.IsProbeQuery()) {
    ownership_handler_->RespondToProbeQuery(message, src);
    return;
  }

  // Else, this is a normal query. Process it as such.
  // This is the case that should be hit 95+% of the time.
  OSP_DVLOG << "Received mDNS Query with " << message.questions().size()
            << " questions. Processing...";
  const std::vector<MdnsRecord>& known_answers = message.answers();
  const std::vector<MdnsQuestion>& questions = message.questions();
  ProcessQueries(src, questions, known_answers);
}

void MdnsResponder::ProcessMultiPacketTruncatedMessage(
    const MdnsMessage& message,
    const IPEndpoint& src) {
  OSP_DVLOG << "Multi-packet truncated message received. Processing...";

  const bool message_has_question = !message.questions().empty();
  const bool message_is_truncated = message.is_truncated();
  OSP_DCHECK(!message_has_question || message_is_truncated);

  auto pair =
      truncated_queries_.emplace(src, std::unique_ptr<TruncatedQuery>());
  std::unique_ptr<TruncatedQuery>& stored_query = pair.first->second;

  // First, handle the case where this host doesn't have a known answer query
  // tracked yet. In this case, start tracking the new query.
  if (pair.second) {
    // Create a new query and swap it with the old one to save an extra lookup.
    auto new_query = std::make_unique<TruncatedQuery>(
        this, task_runner_, now_function_, src, message, config_);
    stored_query.swap(new_query);
    return;
  }

  // Else, there was already a message received from this host.
  const bool are_questions_already_stored = !stored_query->questions().empty();

  // If the new message doesn't have a question, then it must be additional
  // known answers. Add them to the set of known answers for this truncated
  // query.
  if (!message_has_question) {
    stored_query->AddKnownAnswers(message.answers());
    return;
  }

  // Alternatively, if a record for this host existed, it might be because the
  // messages were received out-of-order and known answers have already been
  // received. In this case, associate the new message's query with the known
  // answers already received.
  if (!are_questions_already_stored) {
    stored_query->SetQuery(message);
    return;
  }

  // Else, an ongoing truncated query is already associated with this host and a
  // new one has also been received. This implies one of the following occurred:
  // - The sender must have finished sending packets.
  // - The known answers completing this query somehow got lost on the network.
  // - A second truncated query was started by the same host, and this host
  //   won't be able to differentiate which query future known answers are
  //   associated with.
  // In any of these cases, there's no reason to continue tracking the old
  // query. So process it.
  //
  // Create a new query and swap it with the old one to save an extra lookup.
  auto new_query = std::make_unique<TruncatedQuery>(
      this, task_runner_, now_function_, src, message, config_);
  stored_query.swap(new_query);

  // Now that the pointers have been swapped, process the previously stored
  // query.
  new_query->SendResponse();
}

void MdnsResponder::RespondToTruncatedQuery(TruncatedQuery* query) {
  ProcessQueries(query->src(), query->questions(), query->known_answers());
  auto it = truncated_queries_.find(query->src());

  if (it == truncated_queries_.end()) {
    return;
  }

  // If a second query for this same host arrives, then the question found may
  // not match what is being sent due to the swap done in OnMessageReceived().
  if (it->second.get() == query) {
    truncated_queries_.erase(it);
  }
}

void MdnsResponder::ProcessQueries(
    const IPEndpoint& src,
    const std::vector<MdnsQuestion>& questions,
    const std::vector<MdnsRecord>& known_answers) {
  for (const auto& question : questions) {
    OSP_DVLOG << "\tProcessing mDNS Query for domain: '"
              << question.name().ToString() << "', type: '"
              << question.dns_type() << "' from '" << src << "'";

    // NSEC records should not be queried for.
    if (question.dns_type() == DnsType::kNSEC) {
      continue;
    }

    // Only respond to queries for which one of the following is true:
    // - This host is the sole owner of that domain.
    // - A record corresponding to this question has been published.
    // - The query is a service enumeration query.
    const bool is_service_enumeration = IsServiceTypeEnumerationQuery(question);
    const bool is_exclusive_owner =
        ownership_handler_->IsDomainClaimed(question.name());
    if (!is_service_enumeration && !is_exclusive_owner &&
        !record_handler_->HasRecords(question.name(), question.dns_type(),
                                     question.dns_class())) {
      OSP_DVLOG << "\tmDNS Query processed and no relevant records found!";
      continue;
    } else if (is_service_enumeration) {
      OSP_DVLOG << "\tmDNS Query is for service type enumeration!";
    }

    // Relevant records are published, so send them out using the response type
    // dictated in the question.
    std::function<void(const MdnsMessage&)> send_response;
    if (question.response_type() == ResponseType::kMulticast) {
      send_response = [this](const MdnsMessage& message) {
        sender_->SendMulticast(message);
      };
    } else {
      OSP_DCHECK(question.response_type() == ResponseType::kUnicast);
      send_response = [this, src](const MdnsMessage& message) {
        sender_->SendMessage(message, src);
      };
    }

    // If this host is the exclusive owner, respond immediately. Else, there may
    // be network contention if all hosts respond simultaneously, so delay the
    // response as dictated by RFC 6762.
    if (is_exclusive_owner) {
      SendResponse(question, known_answers, send_response, is_exclusive_owner);
    } else {
      const auto delay = random_delay_->GetSharedRecordResponseDelay();
      std::function<void()> response = [this, question, known_answers,
                                        send_response, is_exclusive_owner]() {
        SendResponse(question, known_answers, send_response,
                     is_exclusive_owner);
      };
      task_runner_->PostTaskWithDelay(response, delay);
    }
  }
}

void MdnsResponder::SendResponse(
    const MdnsQuestion& question,
    const std::vector<MdnsRecord>& known_answers,
    std::function<void(const MdnsMessage&)> send_response,
    bool is_exclusive_owner) {
  OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());

  MdnsMessage message(CreateMessageId(), MessageType::Response);

  if (IsServiceTypeEnumerationQuery(question)) {
    // This is a special case defined in RFC 6763 section 9, so handle it
    // separately.
    ApplyServiceTypeEnumerationResults(&message, record_handler_,
                                       question.name(), question.dns_class());
  } else {
    // NOTE: The exclusive ownership of this record cannot change before this
    // method is called. Exclusive ownership cannot be gained for a record which
    // has previously been published, and if this host is the exclusive owner
    // then this method will have been called without any delay on the task
    // runner.
    ApplyQueryResults(&message, record_handler_, question.name(), known_answers,
                      question.dns_type(), question.dns_class(),
                      is_exclusive_owner);
  }

  // Send the response only if it contains answers to the query.
  OSP_DVLOG << "\tCompleted Processing mDNS Query for domain: '"
            << question.name().ToString() << "', type: '" << question.dns_type()
            << "', with " << message.answers().size() << " results:";
  for (const auto& record : message.answers()) {
    OSP_DVLOG << "\t\tanswer (" << record.ToString() << ")";
  }
  for (const auto& record : message.additional_records()) {
    OSP_DVLOG << "\t\tadditional record ('" << record.ToString() << ")";
  }

  if (!message.answers().empty()) {
    send_response(message);
  }
}

}  // namespace discovery
}  // namespace openscreen
