// 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 "garnet/bin/mdns/service/mdns_service_impl.h"

#include <fuchsia/netstack/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include "garnet/bin/mdns/service/host_name.h"
#include "garnet/bin/mdns/service/mdns_fidl_util.h"
#include "garnet/bin/mdns/service/mdns_names.h"
#include "lib/component/cpp/startup_context.h"
#include "lib/fsl/types/type_converters.h"
#include "lib/fxl/functional/make_copyable.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/type_converter.h"

namespace mdns {
namespace {

static const std::string kPublishAs = "_fuchsia._udp.";
static constexpr uint64_t kPublishPort = 5353;

}  // namespace

MdnsServiceImpl::MdnsServiceImpl(component::StartupContext* startup_context)
    : startup_context_(startup_context) {
  startup_context_->outgoing().AddPublicService(bindings_.GetHandler(this));
  Start();
}

MdnsServiceImpl::~MdnsServiceImpl() {}

void MdnsServiceImpl::Start() {
  // TODO(NET-79): Remove this check when NET-79 is fixed.
  if (!NetworkIsReady()) {
    async::PostDelayedTask(async_get_default_dispatcher(),
                           [this]() { Start(); }, zx::sec(5));
    return;
  }

  mdns_.Start(startup_context_
                  ->ConnectToEnvironmentService<fuchsia::netstack::Netstack>(),
              GetHostName());

  // Publish this device as "_fuchsia._udp.".
  // TODO(dalesat): Make this a config item or delegate to another party.
  PublishServiceInstance(kPublishAs, GetHostName(), kPublishPort,
                         fidl::VectorPtr<fidl::StringPtr>(),
                         [this](fuchsia::mdns::MdnsResult result) {
                           if (result != fuchsia::mdns::MdnsResult::OK) {
                             FXL_LOG(ERROR) << "Failed to publish as "
                                            << kPublishAs << ", result "
                                            << static_cast<uint32_t>(result);
                           }
                         });
}

void MdnsServiceImpl::ResolveHostName(fidl::StringPtr host_name,
                                      uint32_t timeout_ms,
                                      ResolveHostNameCallback callback) {
  if (!MdnsNames::IsValidHostName(host_name)) {
    callback(nullptr, nullptr);
    return;
  }

  mdns_.ResolveHostName(
      host_name,
      fxl::TimePoint::Now() + fxl::TimeDelta::FromMilliseconds(timeout_ms),
      [this, callback = std::move(callback)](
          const std::string& host_name, const inet::IpAddress& v4_address,
          const inet::IpAddress& v6_address) {
        callback(MdnsFidlUtil::CreateSocketAddressIPv4(v4_address),
                 MdnsFidlUtil::CreateSocketAddressIPv6(v6_address));
      });
}

void MdnsServiceImpl::SubscribeToService(
    fidl::StringPtr service_name,
    fidl::InterfaceRequest<fuchsia::mdns::MdnsServiceSubscription>
        subscription_request) {
  if (!MdnsNames::IsValidServiceName(service_name)) {
    return;
  }

  size_t id = next_subscriber_id_++;
  auto subscriber = std::make_unique<Subscriber>(
      std::move(subscription_request),
      [this, id]() { subscribers_by_id_.erase(id); });

  mdns_.SubscribeToService(service_name, subscriber.get());

  subscribers_by_id_.emplace(id, std::move(subscriber));
}

void MdnsServiceImpl::PublishServiceInstance(
    fidl::StringPtr service_name, fidl::StringPtr instance_name, uint16_t port,
    fidl::VectorPtr<fidl::StringPtr> text,
    PublishServiceInstanceCallback callback) {
  if (!MdnsNames::IsValidServiceName(service_name)) {
    callback(fuchsia::mdns::MdnsResult::INVALID_SERVICE_NAME);
    return;
  }

  if (!MdnsNames::IsValidInstanceName(instance_name)) {
    callback(fuchsia::mdns::MdnsResult::INVALID_INSTANCE_NAME);
    return;
  }

  auto publisher = std::make_unique<SimplePublisher>(
      inet::IpPort::From_uint16_t(port), std::move(text), callback.share());

  if (!mdns_.PublishServiceInstance(service_name, instance_name,
                                    publisher.get())) {
    callback(fuchsia::mdns::MdnsResult::ALREADY_PUBLISHED_LOCALLY);
    return;
  }

  MdnsNames::LocalInstanceFullName(instance_name, service_name);

  std::string instance_full_name =
      MdnsNames::LocalInstanceFullName(instance_name, service_name);

  // |Mdns| told us our instance is unique locally, so the full name should
  // not appear in our collection.
  FXL_DCHECK(publishers_by_instance_full_name_.find(instance_full_name) ==
             publishers_by_instance_full_name_.end());

  publishers_by_instance_full_name_.emplace(instance_full_name,
                                            std::move(publisher));
}

void MdnsServiceImpl::UnpublishServiceInstance(fidl::StringPtr service_name,
                                               fidl::StringPtr instance_name) {
  if (!MdnsNames::IsValidServiceName(service_name) ||
      !MdnsNames::IsValidInstanceName(instance_name)) {
    return;
  }

  std::string instance_full_name =
      MdnsNames::LocalInstanceFullName(instance_name, service_name);

  // This will delete the publisher, unpublishing the service instance.
  publishers_by_instance_full_name_.erase(instance_full_name);
}

void MdnsServiceImpl::AddResponder(
    fidl::StringPtr service_name, fidl::StringPtr instance_name,
    fidl::InterfaceHandle<fuchsia::mdns::MdnsResponder> responder_handle) {
  FXL_DCHECK(responder_handle);

  auto responder_ptr = responder_handle.Bind();
  FXL_DCHECK(responder_ptr);

  if (!MdnsNames::IsValidServiceName(service_name)) {
    responder_ptr->UpdateStatus(
        fuchsia::mdns::MdnsResult::INVALID_SERVICE_NAME);
    return;
  }

  if (!MdnsNames::IsValidInstanceName(instance_name)) {
    responder_ptr->UpdateStatus(
        fuchsia::mdns::MdnsResult::INVALID_INSTANCE_NAME);
    return;
  }

  std::string instance_full_name =
      MdnsNames::LocalInstanceFullName(instance_name, service_name);

  auto publisher = std::make_unique<ResponderPublisher>(
      std::move(responder_ptr), [this, instance_full_name]() {
        publishers_by_instance_full_name_.erase(instance_full_name);
      });

  if (!mdns_.PublishServiceInstance(service_name, instance_name,
                                    publisher.get())) {
    publisher->responder_->UpdateStatus(
        fuchsia::mdns::MdnsResult::ALREADY_PUBLISHED_LOCALLY);
    return;
  }

  // |Mdns| told us our instance is unique locally, so the full name should
  // not appear in our collection.
  FXL_DCHECK(publishers_by_instance_full_name_.find(instance_full_name) ==
             publishers_by_instance_full_name_.end());

  publishers_by_instance_full_name_.emplace(instance_full_name,
                                            std::move(publisher));
}

void MdnsServiceImpl::SetSubtypes(fidl::StringPtr service_name,
                                  fidl::StringPtr instance_name,
                                  fidl::VectorPtr<fidl::StringPtr> subtypes) {
  if (!MdnsNames::IsValidServiceName(service_name) ||
      !MdnsNames::IsValidInstanceName(instance_name)) {
    return;
  }

  std::string instance_full_name =
      MdnsNames::LocalInstanceFullName(instance_name, service_name);

  auto iter = publishers_by_instance_full_name_.find(instance_full_name);
  if (iter == publishers_by_instance_full_name_.end()) {
    return;
  }

  iter->second->SetSubtypes(fxl::To<std::vector<std::string>>(subtypes));
}

void MdnsServiceImpl::ReannounceInstance(fidl::StringPtr service_name,
                                         fidl::StringPtr instance_name) {
  if (!MdnsNames::IsValidServiceName(service_name) ||
      !MdnsNames::IsValidInstanceName(instance_name)) {
    return;
  }

  std::string instance_full_name =
      MdnsNames::LocalInstanceFullName(instance_name, service_name);

  auto iter = publishers_by_instance_full_name_.find(instance_full_name);
  if (iter == publishers_by_instance_full_name_.end()) {
    return;
  }

  iter->second->Reannounce();
}

void MdnsServiceImpl::SetVerbose(bool value) { mdns_.SetVerbose(value); }

MdnsServiceImpl::Subscriber::Subscriber(
    fidl::InterfaceRequest<fuchsia::mdns::MdnsServiceSubscription> request,
    fit::closure deleter)
    : binding_(this, std::move(request)) {
  binding_.set_error_handler(
      [this, deleter = std::move(deleter)](zx_status_t status) {
        binding_.set_error_handler(nullptr);
        deleter();
      });

  instances_publisher_.SetCallbackRunner(
      [this](GetInstancesCallback callback, uint64_t version) {
        fidl::VectorPtr<fuchsia::mdns::MdnsServiceInstance> instances(
            instances_by_name_.size());

        size_t i = 0;
        for (auto& pair : instances_by_name_) {
          pair.second->Clone(&instances->at(i++));
        }

        callback(version, std::move(instances));
      });
}

MdnsServiceImpl::Subscriber::~Subscriber() {}

void MdnsServiceImpl::Subscriber::InstanceDiscovered(
    const std::string& service, const std::string& instance,
    const inet::SocketAddress& v4_address,
    const inet::SocketAddress& v6_address,
    const std::vector<std::string>& text) {
  instances_by_name_.emplace(
      instance, MdnsFidlUtil::CreateServiceInstance(
                    service, instance, v4_address, v6_address, text));
}

void MdnsServiceImpl::Subscriber::InstanceChanged(
    const std::string& service, const std::string& instance,
    const inet::SocketAddress& v4_address,
    const inet::SocketAddress& v6_address,
    const std::vector<std::string>& text) {
  auto iter = instances_by_name_.find(instance);
  if (iter != instances_by_name_.end()) {
    MdnsFidlUtil::UpdateServiceInstance(iter->second, v4_address, v6_address,
                                        text);
  }
}

void MdnsServiceImpl::Subscriber::InstanceLost(const std::string& service,
                                               const std::string& instance) {
  instances_by_name_.erase(instance);
}

void MdnsServiceImpl::Subscriber::UpdatesComplete() {
  instances_publisher_.SendUpdates();
}

void MdnsServiceImpl::Subscriber::GetInstances(uint64_t version_last_seen,
                                               GetInstancesCallback callback) {
  instances_publisher_.Get(version_last_seen, std::move(callback));
}

MdnsServiceImpl::SimplePublisher::SimplePublisher(
    inet::IpPort port, fidl::VectorPtr<fidl::StringPtr> text,
    PublishServiceInstanceCallback callback)
    : port_(port),
      text_(fxl::To<std::vector<std::string>>(text)),
      callback_(std::move(callback)) {}

void MdnsServiceImpl::SimplePublisher::ReportSuccess(bool success) {
  callback_(success ? fuchsia::mdns::MdnsResult::OK
                    : fuchsia::mdns::MdnsResult::ALREADY_PUBLISHED_ON_SUBNET);
}

void MdnsServiceImpl::SimplePublisher::GetPublication(
    bool query, const std::string& subtype,
    fit::function<void(std::unique_ptr<Mdns::Publication>)> callback) {
  callback(Mdns::Publication::Create(port_, text_));
}

MdnsServiceImpl::ResponderPublisher::ResponderPublisher(
    fuchsia::mdns::MdnsResponderPtr responder, fit::closure deleter)
    : responder_(std::move(responder)) {
  FXL_DCHECK(responder_);

  responder_.set_error_handler(
      [this, deleter = std::move(deleter)](zx_status_t status) {
        responder_.set_error_handler(nullptr);
        deleter();
      });
}

void MdnsServiceImpl::ResponderPublisher::ReportSuccess(bool success) {
  FXL_DCHECK(responder_);
  responder_->UpdateStatus(
      success ? fuchsia::mdns::MdnsResult::OK
              : fuchsia::mdns::MdnsResult::ALREADY_PUBLISHED_ON_SUBNET);
}

void MdnsServiceImpl::ResponderPublisher::GetPublication(
    bool query, const std::string& subtype,
    fit::function<void(std::unique_ptr<Mdns::Publication>)> callback) {
  FXL_DCHECK(responder_);
  responder_->GetPublication(
      query, subtype,
      fxl::MakeCopyable([callback = std::move(callback)](
                            fuchsia::mdns::MdnsPublicationPtr publication_ptr) {
        callback(MdnsFidlUtil::Convert(publication_ptr));
      }));
}

}  // namespace mdns
