// 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/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/logging.h"
#include "lib/fxl/type_converter.h"

namespace mdns {
namespace {

static const std::string kPublishAs = "_fuchsia._udp.";
static constexpr uint64_t kPublishPort = 5353;
static const std::string kUnsetHostName = "fuchsia-unset-device-name";
static constexpr zx::duration kReadyPollingInterval = zx::sec(1);

std::string GetHostName() {
  char host_name_buffer[HOST_NAME_MAX + 1];
  int result = gethostname(host_name_buffer, sizeof(host_name_buffer));

  std::string host_name;

  if (result < 0) {
    FXL_LOG(ERROR) << "gethostname failed, errno " << errno;
    host_name = kUnsetHostName;
  } else {
    host_name = host_name_buffer;
  }

  return host_name;
}

}  // namespace

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

MdnsServiceImpl::~MdnsServiceImpl() {}

void MdnsServiceImpl::Start() {
  std::string host_name = GetHostName();

  if (host_name == kUnsetHostName) {
    // Host name not set. Try again soon.
    async::PostDelayedTask(
        async_get_default_dispatcher(), [this]() { Start(); },
        kReadyPollingInterval);
    return;
  }

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

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

void MdnsServiceImpl::ResolveHostName(std::string 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(
    std::string service_name,
    fidl::InterfaceRequest<fuchsia::mdns::ServiceSubscription>
        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(
    std::string service_name, std::string instance_name, uint16_t port,
    fidl::VectorPtr<std::string> text,
    PublishServiceInstanceCallback callback) {
  if (!MdnsNames::IsValidServiceName(service_name)) {
    callback(fuchsia::mdns::Result::INVALID_SERVICE_NAME);
    return;
  }

  if (!MdnsNames::IsValidInstanceName(instance_name)) {
    callback(fuchsia::mdns::Result::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::Result::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(std::string service_name,
                                               std::string 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(
    std::string service_name, std::string instance_name,
    fidl::InterfaceHandle<fuchsia::mdns::Responder> 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::Result::INVALID_SERVICE_NAME);
    return;
  }

  if (!MdnsNames::IsValidInstanceName(instance_name)) {
    responder_ptr->UpdateStatus(fuchsia::mdns::Result::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::Result::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(std::string service_name,
                                  std::string instance_name,
                                  std::vector<std::string> 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(std::move(subtypes));
}

void MdnsServiceImpl::ReannounceInstance(std::string service_name,
                                         std::string 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::ServiceSubscription> 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) {
        std::vector<fuchsia::mdns::ServiceInstance> 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<std::string> 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::Result::OK
                    : fuchsia::mdns::Result::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::ResponderPtr 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::Result::OK
              : fuchsia::mdns::Result::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,
      [callback =
           std::move(callback)](fuchsia::mdns::PublicationPtr publication_ptr) {
        callback(MdnsFidlUtil::Convert(publication_ptr));
      });
}

}  // namespace mdns
